]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ada: Fix undefined reference with inline subprogram containing generic instance
authorEric Botcazou <ebotcazou@adacore.com>
Wed, 19 Nov 2025 07:39:20 +0000 (08:39 +0100)
committerMarc Poulhiès <dkm@gcc.gnu.org>
Thu, 27 Nov 2025 12:57:44 +0000 (13:57 +0100)
The problem is that, for an inline subprogram declared in an instance, the
cross-unit inlining machinery does not have the body by the time it decides
to inline calls to the subprogram, because the instantiation of bodies is
deferred until the end of the compilation.  So it cannot see whether this
body contains excluded declarations or statements by that time, typically
nested packages or instances thereof.

The fix is to check that Is_Inlined is still set on the subprogram before
passing it on to the back-end for cross-unit inlining.  It also removes an
obsolete check that was done precisely there.

This also adjusts the description of the -gnatwp switch, which can be used
to get the reason why cross-inlining has failed, for example here:

g.ads:4:01: warning: in instantiation at generic_si.adb:60 [-gnatwp]
g.ads:4:01: warning: cannot inline "*" (nested package instantiation)

gcc/ada/ChangeLog:

PR ada/122574
* doc/gnat_ugn/building_executable_programs_with_gnat.rst (-gnatwp):
Replace reference to -gnatN with -gnatn and adjust accordingly.
* inline.adb: Remove clauses for Exp_Tss.
(Has_Initialized_Type): Delete.
(Add_Inlined_Subprogram): Test that the Is_Inlined flag is still set
on the subprogram.
* usage.adb (Usage): Adjust description of -gnatwp.
* gnat_ugn.texi: Regenerate.

gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst
gcc/ada/gnat_ugn.texi
gcc/ada/inline.adb
gcc/ada/usage.adb

index 703607d2849314e54cefadd829f5f57bae1b69e9..13654e185e0a996cc98f4cacdf28c46ae14d2479 100644 (file)
@@ -3587,13 +3587,13 @@ of the pragma in the :title:`GNAT_Reference_manual`).
 :switch:`-gnatwp`
   *Activate warnings on ineffective pragma Inlines.*
 
-  This switch activates warnings for failure of front end inlining
-  (activated by :switch:`-gnatN`) to inline a particular call. There are
-  many reasons for not being able to inline a call, including most
-  commonly that the call is too complex to inline. The default is
-  that such warnings are not given.
-  Warnings on ineffective inlining by the gcc back end can be activated
-  separately, using the gcc switch -Winline.
+  This switch activates warnings for failure of cross-unit inlining
+  (activated by :switch:`-gnatn`) to inline calls to a subprogram.
+  There are many reasons for not being able to inline these calls,
+  including most commonly that the subprogram body is too complex
+  to inline. The default is that such warnings are not given.
+  Warnings on ineffective inlining (within units) by the back end
+  can be activated separately, using the -Winline switch.
 
 
 .. index:: -gnatwP  (gcc)
index 77db8789ca82ebc6aa2681db9698004fb33daa81..241ded65e8ec54adab403e29720e76e0f0075dc5 100644 (file)
@@ -19,7 +19,7 @@
 
 @copying
 @quotation
-GNAT User's Guide for Native Platforms , Nov 18, 2025
+GNAT User's Guide for Native Platforms , Nov 27, 2025
 
 AdaCore
 
@@ -11942,13 +11942,13 @@ the resulting assigned value is never read.
 
 `Activate warnings on ineffective pragma Inlines.'
 
-This switch activates warnings for failure of front end inlining
-(activated by @code{-gnatN}) to inline a particular call. There are
-many reasons for not being able to inline a call, including most
-commonly that the call is too complex to inline. The default is
-that such warnings are not given.
-Warnings on ineffective inlining by the gcc back end can be activated
-separately, using the gcc switch -Winline.
+This switch activates warnings for failure of cross-unit inlining
+(activated by @code{-gnatn}) to inline calls to a subprogram.
+There are many reasons for not being able to inline these calls,
+including most commonly that the subprogram body is too complex
+to inline. The default is that such warnings are not given.
+Warnings on ineffective inlining (within units) by the back end
+can be activated separately, using the -Winline switch.
 @end table
 
 @geindex -gnatwP (gcc)
index a966c28351f30e1ae1d9d65c9bf10868457bcdee..0cb879a7133a407ed58150494b57ae9b9ad243dc 100644 (file)
@@ -34,7 +34,6 @@ with Elists;         use Elists;
 with Errout;         use Errout;
 with Exp_Ch6;        use Exp_Ch6;
 with Exp_Ch7;        use Exp_Ch7;
-with Exp_Tss;        use Exp_Tss;
 with Exp_Util;       use Exp_Util;
 with Fname;          use Fname;
 with Fname.UF;       use Fname.UF;
@@ -287,10 +286,6 @@ package body Inline is
    --  Return the entity node for the unit containing E. Always return the spec
    --  for a package.
 
-   function Has_Initialized_Type (E : Entity_Id) return Boolean;
-   --  If a candidate for inlining contains type declarations for types with
-   --  nontrivial initialization procedures, they are not worth inlining.
-
    function Has_Single_Return (N : Node_Id) return Boolean;
    --  In general we cannot inline functions that return unconstrained type.
    --  However, we can handle such functions if all return statements return
@@ -758,14 +753,15 @@ package body Inline is
       --  an instance whose body will be analyzed anyway or the subprogram was
       --  generated as a body by the compiler (for example an initialization
       --  procedure) or its declaration was provided along with the body (for
-      --  example an expression function) and it does not declare types with
-      --  nontrivial initialization procedures.
+      --  example an expression function). Note that we need to test again the
+      --  Is_Inlined flag because Analyze_Subprogram_Body_Helper may have reset
+      --  it if the body contains excluded declarations or statements.
 
       if (Is_Inlined (Pack)
            or else Is_Generic_Instance (Pack)
            or else Nkind (Decl) = N_Subprogram_Body
            or else Present (Corresponding_Body (Decl)))
-        and then not Has_Initialized_Type (E)
+        and then Is_Inlined (E)
       then
          Register_Backend_Inlined_Subprogram (E);
 
@@ -4528,35 +4524,6 @@ package body Inline is
       return False;
    end Has_Excluded_Statement;
 
-   --------------------------
-   -- Has_Initialized_Type --
-   --------------------------
-
-   function Has_Initialized_Type (E : Entity_Id) return Boolean is
-      E_Body : constant Node_Id := Subprogram_Body (E);
-      Decl   : Node_Id;
-
-   begin
-      if No (E_Body) then -- imported subprogram
-         return False;
-
-      else
-         Decl := First (Declarations (E_Body));
-         while Present (Decl) loop
-            if Nkind (Decl) = N_Full_Type_Declaration
-              and then Comes_From_Source (Decl)
-              and then Present (Init_Proc (Defining_Identifier (Decl)))
-            then
-               return True;
-            end if;
-
-            Next (Decl);
-         end loop;
-      end if;
-
-      return False;
-   end Has_Initialized_Type;
-
    -----------------------
    -- Has_Single_Return --
    -----------------------
index bf8417a92c85f0b190f291597e05197cf4451056..868ecd850001dff7f0bf41bf2cdeb83cf918ae2b 100644 (file)
@@ -562,9 +562,9 @@ begin
    Write_Line ("        .O*  turn off warnings for out parameters assigned " &
                                                   "but not read");
    Write_Line ("        p+   turn on warnings for ineffective pragma " &
-                                                  "Inline in frontend");
+                                                  "Inline");
    Write_Line ("        P*   turn off warnings for ineffective pragma " &
-                                                  "Inline in frontend");
+                                                  "Inline");
    Write_Line ("        .p+  turn on warnings for suspicious parameter " &
                                                   "order");
    Write_Line ("        .P*  turn off warnings for suspicious parameter " &