[Ada] Lift restriction on instantiations that are compilation units
authorEric Botcazou <ebotcazou@adacore.com>
Mon, 19 Aug 2019 08:36:53 +0000 (08:36 +0000)
committerPierre-Marie de Rodat <pmderodat@gcc.gnu.org>
Mon, 19 Aug 2019 08:36:53 +0000 (08:36 +0000)
This change lifts the restriction that was still present in the new
on-demand instantiation scheme for the body of generics instantiated in
non-main units.

The instantiations that are compilation units were still dealt with in
the old-fashioned way, that is to say the decision of instantiating the
body was still made up front during the analysis of the instance
declaration, instead of being deferred until after a call to an inlined
subprogram is encountered.

This should save a few more cycles when full inlining across units is
enabled, but there should otherwise be no functional changes.

2019-08-19  Eric Botcazou  <ebotcazou@adacore.com>

gcc/ada/

* inline.adb (Add_Inlined_Body): Do not special-case instances
that are compilation units.
(Add_Pending_Instantiation): Likewise.
(Instantiate_Body): Skip instantiations that are compilation
units and have already been performed.
* sem_ch12.adb (Needs_Body_Instantiated): Do not special-case
instances that are compilation units.
(Load_Parent_Of_Generic): Be prepared for parent that is a
compilation unit but whose instantiation node has not been
replaced.

gcc/testsuite/

* gnat.dg/generic_inst12.adb, gnat.dg/generic_inst12_pkg1.adb,
gnat.dg/generic_inst12_pkg1.ads,
gnat.dg/generic_inst12_pkg2.ads: New testcase.

From-SVN: r274657

gcc/ada/ChangeLog
gcc/ada/inline.adb
gcc/ada/sem_ch12.adb
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/generic_inst12.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/generic_inst12_pkg1.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/generic_inst12_pkg1.ads [new file with mode: 0644]
gcc/testsuite/gnat.dg/generic_inst12_pkg2.ads [new file with mode: 0644]

index c801498bc2a541216034ef5e225b093264ab7e4a..2ac5309292f8330df1f9370e42950395a8396854 100644 (file)
@@ -1,3 +1,16 @@
+2019-08-19  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * inline.adb (Add_Inlined_Body): Do not special-case instances
+       that are compilation units.
+       (Add_Pending_Instantiation): Likewise.
+       (Instantiate_Body): Skip instantiations that are compilation
+       units and have already been performed.
+       * sem_ch12.adb (Needs_Body_Instantiated): Do not special-case
+       instances that are compilation units.
+       (Load_Parent_Of_Generic): Be prepared for parent that is a
+       compilation unit but whose instantiation node has not been
+       replaced.
+
 2019-08-19  Eric Botcazou  <ebotcazou@adacore.com>
 
        * inline.adb (Initialize, Lock): Deal with
index 22a50e2b056141bded75912bc6afec74291847cd..46daa487e709b3e1a616a6cc3aa0d00da6ecc001 100644 (file)
@@ -611,12 +611,11 @@ package body Inline is
                   Inst_Decl := Unit_Declaration_Node (Inst);
 
                   --  Do not inline the instance if the body already exists,
-                  --  or if the instance is a compilation unit, or else if
-                  --  the instance node is simply missing.
+                  --  or the instance node is simply missing.
 
                   if Present (Corresponding_Body (Inst_Decl))
-                    or else Nkind (Parent (Inst_Decl)) = N_Compilation_Unit
-                    or else No (Next (Inst_Decl))
+                    or else (Nkind (Parent (Inst_Decl)) /= N_Compilation_Unit
+                              and then No (Next (Inst_Decl)))
                   then
                      Set_Is_Called (Inst);
                   else
@@ -797,13 +796,11 @@ package body Inline is
 
          To_Pending_Instantiations.Set (Act_Decl, Index);
 
-         --  If an instantiation is either a compilation unit or is in the main
-         --  unit or subunit or is a nested subprogram, then its body is needed
-         --  as per the analysis already done in Analyze_Package_Instantiation
-         --  and Analyze_Subprogram_Instantiation.
+         --  If an instantiation is in the main unit or subunit, or is a nested
+         --  subprogram, then its body is needed as per the analysis done in
+         --  Analyze_Package_Instantiation & Analyze_Subprogram_Instantiation.
 
-         if Nkind (Parent (Inst)) = N_Compilation_Unit
-           or else In_Main_Unit_Or_Subunit (Act_Decl_Id)
+         if In_Main_Unit_Or_Subunit (Act_Decl_Id)
            or else (Is_Subprogram (Act_Decl_Id)
                      and then Is_Nested (Act_Decl_Id))
          then
@@ -4460,6 +4457,13 @@ package body Inline is
          if No (Info.Inst_Node) then
             null;
 
+         --  If the instantiation node is a package body, this means that the
+         --  instance is a compilation unit and the instantiation has already
+         --  been performed by Build_Instance_Compilation_Unit_Nodes.
+
+         elsif Nkind (Info.Inst_Node) = N_Package_Body then
+            null;
+
          elsif Nkind (Info.Act_Decl) = N_Package_Declaration then
             Instantiate_Package_Body (Info);
             Add_Scope_To_Clean (Defining_Entity (Info.Act_Decl));
index e94fc210db205516f453edf7c28d3a3c1df9cf1e..17de328d29f081b7de110a16e1dc192275e18d3b 100644 (file)
@@ -3921,19 +3921,15 @@ package body Sem_Ch12 is
             return False;
          end if;
 
-         --  Here we have a special handling for back-end inlining: if the
-         --  instantiation is not a compilation unit, then we want to have
-         --  its body instantiated. The reason is that Might_Inline_Subp
-         --  does not catch all the cases (since it does not recurse into
-         --  nested packages) so this avoids the need to patch things up
-         --  at a later stage. Moreover the instantiations that are not
-         --  compilation units are only performed on demand when back-end
+         --  Here we have a special handling for back-end inlining: if inline
+         --  processing is required, then we unconditionally want to have the
+         --  body instantiated. The reason is that Might_Inline_Subp does not
+         --  catch all the cases (as it does not recurse into nested packages)
+         --  so this avoids the need to patch things up afterwards. Moreover,
+         --  these instantiations are only performed on demand when back-end
          --  inlining is enabled, so this causes very little extra work.
 
-         if Nkind (Parent (N)) /= N_Compilation_Unit
-           and then Inline_Processing_Required
-           and then Back_End_Inlining
-         then
+         if Inline_Processing_Required and then Back_End_Inlining then
             return True;
          end if;
 
@@ -13699,15 +13695,26 @@ package body Sem_Ch12 is
               and then
                 Nkind (Original_Node (True_Parent)) = N_Package_Instantiation
             then
-               --  Parent is a compilation unit that is an instantiation.
-               --  Instantiation node has been replaced with package decl.
+               --  Parent is a compilation unit that is an instantiation, and
+               --  instantiation node has been replaced with package decl.
 
                Inst_Node := Original_Node (True_Parent);
                exit;
 
             elsif Nkind (True_Parent) = N_Package_Declaration
-              and then Present (Generic_Parent (Specification (True_Parent)))
+             and then Nkind (Parent (True_Parent)) = N_Compilation_Unit
+             and then
+               Nkind (Unit (Parent (True_Parent))) = N_Package_Instantiation
+            then
+               --  Parent is a compilation unit that is an instantiation, but
+               --  instantiation node has not been replaced with package decl.
+
+               Inst_Node := Unit (Parent (True_Parent));
+               exit;
+
+            elsif Nkind (True_Parent) = N_Package_Declaration
               and then Nkind (Parent (True_Parent)) /= N_Compilation_Unit
+              and then Present (Generic_Parent (Specification (True_Parent)))
             then
                --  Parent is an instantiation within another specification.
                --  Declaration for instance has been inserted before original
index f3cff77d8e8ec17da6d20a5922c671f5ee0cdc41..0f246bf7bd17d0db1eaaab5e9b71222450c7c16f 100644 (file)
@@ -1,3 +1,9 @@
+2019-08-19  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gnat.dg/generic_inst12.adb, gnat.dg/generic_inst12_pkg1.adb,
+       gnat.dg/generic_inst12_pkg1.ads,
+       gnat.dg/generic_inst12_pkg2.ads: New testcase.
+
 2019-08-19  Ed Schonberg  <schonberg@adacore.com>
 
        * gnat.dg/warn28.adb, gnat.dg/warn28.ads: New testcase.
diff --git a/gcc/testsuite/gnat.dg/generic_inst12.adb b/gcc/testsuite/gnat.dg/generic_inst12.adb
new file mode 100644 (file)
index 0000000..4f99749
--- /dev/null
@@ -0,0 +1,12 @@
+--  { dg-do run }
+--  { dg-options "-O -gnatn" }
+with Generic_Inst12_Pkg2;
+
+procedure Generic_Inst12 is
+
+  procedure My_Inner_G is new Generic_Inst12_Pkg2.Inner_G;
+
+begin
+  My_Inner_G (1);
+  Generic_Inst12_Pkg2.Proc (1);
+end;
diff --git a/gcc/testsuite/gnat.dg/generic_inst12_pkg1.adb b/gcc/testsuite/gnat.dg/generic_inst12_pkg1.adb
new file mode 100644 (file)
index 0000000..e4eced5
--- /dev/null
@@ -0,0 +1,13 @@
+package body Generic_Inst12_Pkg1 is
+
+  procedure Inner_G (Val : T) is
+  begin
+    null;
+  end;
+
+  procedure Proc (Val : T) is
+  begin
+    null;
+  end;
+
+end Generic_Inst12_Pkg1;
diff --git a/gcc/testsuite/gnat.dg/generic_inst12_pkg1.ads b/gcc/testsuite/gnat.dg/generic_inst12_pkg1.ads
new file mode 100644 (file)
index 0000000..27de7cb
--- /dev/null
@@ -0,0 +1,11 @@
+generic
+  type T is private;
+package Generic_Inst12_Pkg1 is
+
+  generic
+  procedure Inner_G (Val : T);
+
+  procedure Proc (Val : T);
+  pragma Inline (Proc);
+
+end Generic_Inst12_Pkg1;
diff --git a/gcc/testsuite/gnat.dg/generic_inst12_pkg2.ads b/gcc/testsuite/gnat.dg/generic_inst12_pkg2.ads
new file mode 100644 (file)
index 0000000..60519ad
--- /dev/null
@@ -0,0 +1,3 @@
+with Generic_Inst12_Pkg1;
+
+package Generic_Inst12_Pkg2 is new Generic_Inst12_Pkg1 (Integer);