aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada
diff options
context:
space:
mode:
authorArnaud Charlet <charlet@gcc.gnu.org>2014-07-31 15:56:11 +0200
committerArnaud Charlet <charlet@gcc.gnu.org>2014-07-31 15:56:11 +0200
commit6c26bac268904dcdf7719bdc073f288a2c06703d (patch)
treedc790bc4944cf9c7404983c0805543add2e62e4f /gcc/ada
parent0c9aebea0f70c507b2eb63dd83c5f0ff3ee55793 (diff)
downloadgcc-6c26bac268904dcdf7719bdc073f288a2c06703d.zip
gcc-6c26bac268904dcdf7719bdc073f288a2c06703d.tar.gz
gcc-6c26bac268904dcdf7719bdc073f288a2c06703d.tar.bz2
[multiple changes]
2014-07-31 Javier Miranda <miranda@adacore.com> * debug.adb Remove documentation of -gnatd.k (no longer needed). * sem_ch6.adb (Analyze_Subprogram_Body_Helper): Code cleanup. * inline.ads (Backend_Inlined_Subps): New Elist. (Backend_Not_Inlined_Subps): New Elist. (Has_Excluded_Declaration): Declaration previously located in * inline.adb (Has_Excluded_Statement): Declaration previously located in inline.adb * inline.adb (Has_Single_Return): Moved out of Build_Body_To_Inline to avoid having duplicated code. (Number_Of_Statements): New subprogram. (Register_Backend_Inlined_Subprogram): New subprogram. (Register_Backend_Not_Inlined_Subprogram): New subprogram. (Add_Inlined_Subprogram): Register backend inlined subprograms and also register subprograms that cannot be inlined by the backend. (Has_Excluded_Declaration): Moved out of Build_Body_To_Inline to avoid having duplicated code. Replace occurrences of Debug_Flag_Dot_K by Back_End_Inlining. * sem_res.adb (Resolve_Call): Code cleanup. * exp_ch6.adb (Expand_Call): Complete previous patch. Replace occurrence of Debug_Flag_Dot_K by Back_End_Inlining. (List_Inlining_Info): Add listing of subprograms passed to the backend and listing of subprograms that cannot be inlined by the backend. * sem_ch12.adb, sem_ch3.adb Replace occurrences of Debug_Flag_Dot_K by Back_End_Inlining. 2014-07-31 Robert Dewar <dewar@adacore.com> * nlists.ads: Minor code fix (remove unwise Inline for List_Length). From-SVN: r213373
Diffstat (limited to 'gcc/ada')
-rw-r--r--gcc/ada/ChangeLog34
-rw-r--r--gcc/ada/debug.adb6
-rw-r--r--gcc/ada/exp_ch6.adb92
-rw-r--r--gcc/ada/inline.adb853
-rw-r--r--gcc/ada/inline.ads21
-rw-r--r--gcc/ada/nlists.ads3
-rw-r--r--gcc/ada/sem_ch12.adb5
-rw-r--r--gcc/ada/sem_ch3.adb2
-rw-r--r--gcc/ada/sem_ch6.adb109
-rw-r--r--gcc/ada/sem_res.adb9
10 files changed, 620 insertions, 514 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index db882b0..e3f2fa3 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,36 @@
+2014-07-31 Javier Miranda <miranda@adacore.com>
+
+ * debug.adb Remove documentation of -gnatd.k (no longer needed).
+ * sem_ch6.adb (Analyze_Subprogram_Body_Helper): Code cleanup.
+ * inline.ads (Backend_Inlined_Subps): New
+ Elist. (Backend_Not_Inlined_Subps): New Elist.
+ (Has_Excluded_Declaration): Declaration previously located in
+ * inline.adb (Has_Excluded_Statement): Declaration previously
+ located in inline.adb
+ * inline.adb (Has_Single_Return): Moved out of
+ Build_Body_To_Inline to avoid having duplicated code.
+ (Number_Of_Statements): New subprogram.
+ (Register_Backend_Inlined_Subprogram): New subprogram.
+ (Register_Backend_Not_Inlined_Subprogram): New subprogram.
+ (Add_Inlined_Subprogram): Register backend inlined subprograms and
+ also register subprograms that cannot be inlined by the backend.
+ (Has_Excluded_Declaration): Moved out of Build_Body_To_Inline
+ to avoid having duplicated code. Replace occurrences of
+ Debug_Flag_Dot_K by Back_End_Inlining.
+ * sem_res.adb (Resolve_Call): Code cleanup.
+ * exp_ch6.adb (Expand_Call): Complete previous patch. Replace
+ occurrence of Debug_Flag_Dot_K by Back_End_Inlining.
+ (List_Inlining_Info): Add listing of subprograms passed to the
+ backend and listing of subprograms that cannot be inlined by
+ the backend.
+ * sem_ch12.adb, sem_ch3.adb Replace occurrences of
+ Debug_Flag_Dot_K by Back_End_Inlining.
+
+2014-07-31 Robert Dewar <dewar@adacore.com>
+
+ * nlists.ads: Minor code fix (remove unwise Inline for
+ List_Length).
+
2014-07-31 Arnaud Charlet <charlet@adacore.com>
* einfo.adb: Remove VMS specific code.
@@ -14,6 +47,7 @@
* gcc-interface/trans.c, gcc-interface/misc.c: Remove references
to VMS. Misc clean ups.
+ * gcc-interface/Makefile.in (gnatlib-shared-vms): Remove.
2014-07-31 Robert Dewar <dewar@adacore.com>
diff --git a/gcc/ada/debug.adb b/gcc/ada/debug.adb
index 9bf4faf..94da8ec 100644
--- a/gcc/ada/debug.adb
+++ b/gcc/ada/debug.adb
@@ -101,7 +101,7 @@ package body Debug is
-- d.h
-- d.i Ignore Warnings pragmas
-- d.j Generate listing of frontend inlined calls
- -- d.k Enable new support for frontend inlining
+ -- d.k
-- d.l Use Ada 95 semantics for limited function returns
-- d.m For -gnatl, print full source only for main unit
-- d.n Print source file names
@@ -533,10 +533,6 @@ package body Debug is
-- to the backend. This is useful to locate skipped calls that must be
-- inlined by the frontend.
- -- d.k Enable new semantics of frontend inlining. This is useful to test
- -- this new feature in all the platforms. What *is* this new semantics
- -- which doesn't seem to be documented anywhere???
-
-- d.l Use Ada 95 semantics for limited function returns. This may be
-- used to work around the incompatibility introduced by AI-318-2.
-- It is useful only in -gnat05 mode.
diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb
index a119888..561fdfc 100644
--- a/gcc/ada/exp_ch6.adb
+++ b/gcc/ada/exp_ch6.adb
@@ -3830,15 +3830,14 @@ package body Exp_Ch6 is
return;
end if;
- -- Back end inlining: let the back end handle it
+ -- Handle inlining. No action needed if the subprogram is not inlined
- if Back_End_Inlining and then Is_Inlined (Subp) then
- Add_Inlined_Body (Subp);
- Register_Backend_Call (Call_Node);
+ if not Is_Inlined (Subp) then
+ null;
- -- Handle inlining (old semantics)
+ -- Handle frontend inlining
- elsif Is_Inlined (Subp) and then not Debug_Flag_Dot_K then
+ elsif not Back_End_Inlining then
Inlined_Subprogram : declare
Bod : Node_Id;
Must_Inline : Boolean := False;
@@ -3924,9 +3923,22 @@ package body Exp_Ch6 is
end if;
end Inlined_Subprogram;
- -- Handle inlining (new semantics)
+ -- Back end inlining: let the back end handle it
+
+ elsif No (Unit_Declaration_Node (Subp))
+ or else
+ Nkind (Unit_Declaration_Node (Subp)) /= N_Subprogram_Declaration
+ or else
+ No (Body_To_Inline (Unit_Declaration_Node (Subp)))
+ then
+ Add_Inlined_Body (Subp);
+ Register_Backend_Call (Call_Node);
+
+ -- Frontend expansion of supported functions returning unconstrained
+ -- types
- elsif Is_Inlined (Subp) then
+ else pragma Assert (Ekind (Subp) = E_Function
+ and then Returns_Unconstrained_Type (Subp));
declare
Spec : constant Node_Id := Unit_Declaration_Node (Subp);
@@ -9720,6 +9732,70 @@ package body Exp_Ch6 is
Next_Elmt (Elmt);
end loop;
end if;
+
+ -- Generate listing of subprograms passed to the backend
+
+ if Present (Backend_Inlined_Subps)
+ and then Back_End_Inlining
+ then
+ Count := 0;
+
+ Elmt := First_Elmt (Backend_Inlined_Subps);
+ while Present (Elmt) loop
+ Nod := Node (Elmt);
+
+ Count := Count + 1;
+
+ if Count = 1 then
+ Write_Str
+ ("Listing of inlined subprograms passed to the backend");
+ Write_Eol;
+ end if;
+
+ Write_Str (" ");
+ Write_Int (Count);
+ Write_Str (":");
+ Write_Name (Chars (Nod));
+ Write_Str (" (");
+ Write_Location (Sloc (Nod));
+ Write_Str (")");
+ Output.Write_Eol;
+
+ Next_Elmt (Elmt);
+ end loop;
+ end if;
+
+ -- Generate listing of subprogram that cannot be inlined by the backend
+
+ if Present (Backend_Not_Inlined_Subps)
+ and then Back_End_Inlining
+ then
+ Count := 0;
+
+ Elmt := First_Elmt (Backend_Not_Inlined_Subps);
+ while Present (Elmt) loop
+ Nod := Node (Elmt);
+
+ Count := Count + 1;
+
+ if Count = 1 then
+ Write_Str
+ ("Listing of subprograms that cannot inline the backend");
+ Write_Eol;
+ end if;
+
+ Write_Str (" ");
+ Write_Int (Count);
+ Write_Str (":");
+ Write_Name (Chars (Nod));
+ Write_Str (" (");
+ Write_Location (Sloc (Nod));
+ Write_Str (")");
+ Output.Write_Eol;
+
+ Next_Elmt (Elmt);
+ end loop;
+ end if;
end List_Inlining_Info;
end Exp_Ch6;
diff --git a/gcc/ada/inline.adb b/gcc/ada/inline.adb
index c8fdc32..a2d41b2 100644
--- a/gcc/ada/inline.adb
+++ b/gcc/ada/inline.adb
@@ -24,7 +24,6 @@
------------------------------------------------------------------------------
with Atree; use Atree;
-with Debug; use Debug;
with Einfo; use Einfo;
with Elists; use Elists;
with Errout; use Errout;
@@ -143,27 +142,37 @@ package body Inline is
-- Local Subprograms --
-----------------------
- function Get_Code_Unit_Entity (E : Entity_Id) return Entity_Id;
- pragma Inline (Get_Code_Unit_Entity);
- -- Return the entity node for the unit containing E. Always return the spec
- -- for a package.
-
- function In_Main_Unit_Or_Subunit (E : Entity_Id) return Boolean;
- -- Return True if E is in the main unit or its spec or in a subunit
-
procedure Add_Call (Called : Entity_Id; Caller : Entity_Id := Empty);
-- Make two entries in Inlined table, for an inlined subprogram being
-- called, and for the inlined subprogram that contains the call. If
-- the call is in the main compilation unit, Caller is Empty.
+ procedure Add_Inlined_Subprogram (Index : Subp_Index);
+ -- Add the subprogram to the list of inlined subprogram for the unit
+
function Add_Subp (E : Entity_Id) return Subp_Index;
-- Make entry in Inlined table for subprogram E, or return table index
-- that already holds E.
+ function Get_Code_Unit_Entity (E : Entity_Id) return Entity_Id;
+ pragma Inline (Get_Code_Unit_Entity);
+ -- 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
-- non-trivial 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
+ -- a local variable that is the only declaration in the body of the
+ -- function. In that case the call can be replaced by that local
+ -- variable as is done for other inlined calls.
+
+ function In_Main_Unit_Or_Subunit (E : Entity_Id) return Boolean;
+ -- Return True if E is in the main unit or its spec or in a subunit
+
function Is_Nested (E : Entity_Id) return Boolean;
-- If the function is nested inside some other function, it will always
-- be compiled if that function is, so don't add it to the inline list.
@@ -171,8 +180,8 @@ package body Inline is
-- function anyway. This is also the case if the function is defined in a
-- task body or within an entry (for example, an initialization procedure).
- procedure Add_Inlined_Subprogram (Index : Subp_Index);
- -- Add the subprogram to the list of inlined subprogram for the unit
+ function Number_Of_Statements (Stats : List_Id) return Natural;
+ -- Return the number of statements in the list
------------------------------
-- Deferred Cleanup Actions --
@@ -415,6 +424,13 @@ package body Inline is
--
-- This procedure must be carefully coordinated with the back end.
+ procedure Register_Backend_Inlined_Subprogram (Subp : Entity_Id);
+ -- Append Subp to the list of subprograms inlined by the backend
+
+ procedure Register_Backend_Not_Inlined_Subprogram (Subp : Entity_Id);
+ -- Append Subp to the list of subprograms that cannot be inlined by
+ -- the backend
+
----------------------------
-- Back_End_Cannot_Inline --
----------------------------
@@ -461,6 +477,32 @@ package body Inline is
return False;
end Back_End_Cannot_Inline;
+ -----------------------------------------
+ -- Register_Backend_Inlined_Subprogram --
+ -----------------------------------------
+
+ procedure Register_Backend_Inlined_Subprogram (Subp : Entity_Id) is
+ begin
+ if Backend_Inlined_Subps = No_Elist then
+ Backend_Inlined_Subps := New_Elmt_List;
+ end if;
+
+ Append_Elmt (Subp, To => Backend_Inlined_Subps);
+ end Register_Backend_Inlined_Subprogram;
+
+ ---------------------------------------------
+ -- Register_Backend_Not_Inlined_Subprogram --
+ ---------------------------------------------
+
+ procedure Register_Backend_Not_Inlined_Subprogram (Subp : Entity_Id) is
+ begin
+ if Backend_Not_Inlined_Subps = No_Elist then
+ Backend_Not_Inlined_Subps := New_Elmt_List;
+ end if;
+
+ Append_Elmt (Subp, To => Backend_Not_Inlined_Subps);
+ end Register_Backend_Not_Inlined_Subprogram;
+
-- Start of processing for Add_Inlined_Subprogram
begin
@@ -480,8 +522,11 @@ package body Inline is
then
if Back_End_Cannot_Inline (E) then
Set_Is_Inlined (E, False);
+ Register_Backend_Not_Inlined_Subprogram (E);
else
+ Register_Backend_Inlined_Subprogram (E);
+
if No (Last_Inlined) then
Set_First_Inlined_Subprogram (Cunit (Main_Unit), E);
else
@@ -490,6 +535,8 @@ package body Inline is
Last_Inlined := E;
end if;
+ else
+ Register_Backend_Not_Inlined_Subprogram (E);
end if;
Inlined.Table (Index).Listed := True;
@@ -850,9 +897,6 @@ package body Inline is
Max_Size : constant := 10;
Stat_Count : Integer := 0;
- function Has_Excluded_Declaration (Decls : List_Id) return Boolean;
- -- Check for declarations that make inlining not worthwhile
-
function Has_Excluded_Statement (Stats : List_Id) return Boolean;
-- Check for statements that make inlining not worthwhile: any tasking
-- statement, nested at any level. Keep track of total number of
@@ -865,13 +909,6 @@ package body Inline is
-- conflict with subsequent inlinings, so that it is unsafe to try to
-- inline in such a case.
- function Has_Single_Return return Boolean;
- -- In general we cannot inline functions that return unconstrained type.
- -- However, we can handle such functions if all return statements return
- -- a local variable that is the only declaration in the body of the
- -- function. In that case the call can be replaced by that local
- -- variable as is done for other inlined calls.
-
function Has_Single_Return_In_GNATprove_Mode return Boolean;
-- This function is called only in GNATprove mode, and it returns
-- True if the subprogram has no or a single return statement as
@@ -888,103 +925,6 @@ package body Inline is
-- unconstrained type, the secondary stack is involved, and it
-- is not worth inlining.
- ------------------------------
- -- Has_Excluded_Declaration --
- ------------------------------
-
- function Has_Excluded_Declaration (Decls : List_Id) return Boolean is
- D : Node_Id;
-
- function Is_Unchecked_Conversion (D : Node_Id) return Boolean;
- -- Nested subprograms make a given body ineligible for inlining, but
- -- we make an exception for instantiations of unchecked conversion.
- -- The body has not been analyzed yet, so check the name, and verify
- -- that the visible entity with that name is the predefined unit.
-
- -----------------------------
- -- Is_Unchecked_Conversion --
- -----------------------------
-
- function Is_Unchecked_Conversion (D : Node_Id) return Boolean is
- Id : constant Node_Id := Name (D);
- Conv : Entity_Id;
-
- begin
- if Nkind (Id) = N_Identifier
- and then Chars (Id) = Name_Unchecked_Conversion
- then
- Conv := Current_Entity (Id);
-
- elsif Nkind_In (Id, N_Selected_Component, N_Expanded_Name)
- and then Chars (Selector_Name (Id)) = Name_Unchecked_Conversion
- then
- Conv := Current_Entity (Selector_Name (Id));
- else
- return False;
- end if;
-
- return Present (Conv)
- and then Is_Predefined_File_Name
- (Unit_File_Name (Get_Source_Unit (Conv)))
- and then Is_Intrinsic_Subprogram (Conv);
- end Is_Unchecked_Conversion;
-
- -- Start of processing for Has_Excluded_Declaration
-
- begin
- D := First (Decls);
- while Present (D) loop
- if Nkind (D) = N_Function_Instantiation
- and then not Is_Unchecked_Conversion (D)
- then
- Cannot_Inline
- ("cannot inline & (nested function instantiation)?",
- D, Subp);
- return True;
-
- elsif Nkind (D) = N_Protected_Type_Declaration then
- Cannot_Inline
- ("cannot inline & (nested protected type declaration)?",
- D, Subp);
- return True;
-
- elsif Nkind (D) = N_Package_Declaration then
- Cannot_Inline
- ("cannot inline & (nested package declaration)?",
- D, Subp);
- return True;
-
- elsif Nkind (D) = N_Package_Instantiation then
- Cannot_Inline
- ("cannot inline & (nested package instantiation)?",
- D, Subp);
- return True;
-
- elsif Nkind (D) = N_Subprogram_Body then
- Cannot_Inline
- ("cannot inline & (nested subprogram)?",
- D, Subp);
- return True;
-
- elsif Nkind (D) = N_Procedure_Instantiation then
- Cannot_Inline
- ("cannot inline & (nested procedure instantiation)?",
- D, Subp);
- return True;
-
- elsif Nkind (D) = N_Task_Type_Declaration then
- Cannot_Inline
- ("cannot inline & (nested task type declaration)?",
- D, Subp);
- return True;
- end if;
-
- Next (D);
- end loop;
-
- return False;
- end Has_Excluded_Declaration;
-
----------------------------
-- Has_Excluded_Statement --
----------------------------
@@ -1012,7 +952,7 @@ package body Inline is
elsif Nkind (S) = N_Block_Statement then
if Present (Declarations (S))
- and then Has_Excluded_Declaration (Declarations (S))
+ and then Has_Excluded_Declaration (Subp, Declarations (S))
then
return True;
@@ -1108,89 +1048,6 @@ package body Inline is
return False;
end Has_Pending_Instantiation;
- ------------------------
- -- Has_Single_Return --
- ------------------------
-
- function Has_Single_Return return Boolean is
- Return_Statement : Node_Id := Empty;
-
- function Check_Return (N : Node_Id) return Traverse_Result;
-
- ------------------
- -- Check_Return --
- ------------------
-
- function Check_Return (N : Node_Id) return Traverse_Result is
- begin
- if Nkind (N) = N_Simple_Return_Statement then
- if Present (Expression (N))
- and then Is_Entity_Name (Expression (N))
- then
- if No (Return_Statement) then
- Return_Statement := N;
- return OK;
-
- elsif Chars (Expression (N)) =
- Chars (Expression (Return_Statement))
- then
- return OK;
-
- else
- return Abandon;
- end if;
-
- -- A return statement within an extended return is a noop
- -- after inlining.
-
- elsif No (Expression (N))
- and then Nkind (Parent (Parent (N))) =
- N_Extended_Return_Statement
- then
- return OK;
-
- else
- -- Expression has wrong form
-
- return Abandon;
- end if;
-
- -- We can only inline a build-in-place function if
- -- it has a single extended return.
-
- elsif Nkind (N) = N_Extended_Return_Statement then
- if No (Return_Statement) then
- Return_Statement := N;
- return OK;
-
- else
- return Abandon;
- end if;
-
- else
- return OK;
- end if;
- end Check_Return;
-
- function Check_All_Returns is new Traverse_Func (Check_Return);
-
- -- Start of processing for Has_Single_Return
-
- begin
- if Check_All_Returns (N) /= OK then
- return False;
-
- elsif Nkind (Return_Statement) = N_Extended_Return_Statement then
- return True;
-
- else
- return Present (Declarations (N))
- and then Present (First (Declarations (N)))
- and then Chars (Expression (Return_Statement)) =
- Chars (Defining_Identifier (First (Declarations (N))));
- end if;
- end Has_Single_Return;
-
-----------------------------------------
-- Has_Single_Return_In_GNATprove_Mode --
-----------------------------------------
@@ -1330,7 +1187,7 @@ package body Inline is
and then not Is_Access_Type (Etype (Subp))
and then not Is_Constrained (Etype (Subp))
then
- if not Has_Single_Return then
+ if not Has_Single_Return (N) then
Cannot_Inline
("cannot inline & (unconstrained return type)?", N, Subp);
return;
@@ -1348,7 +1205,7 @@ package body Inline is
end if;
if Present (Declarations (N))
- and then Has_Excluded_Declaration (Declarations (N))
+ and then Has_Excluded_Declaration (Subp, Declarations (N))
then
return;
end if;
@@ -1502,7 +1359,7 @@ package body Inline is
-- Old semantics
- if not Debug_Flag_Dot_K then
+ if not Back_End_Inlining then
-- Do not emit warning if this is a predefined unit which is not
-- the main unit. With validity checks enabled, some predefined
@@ -1939,19 +1796,10 @@ package body Inline is
Subp : Entity_Id) return Boolean
is
Max_Size : constant := 10;
- Stat_Count : Integer := 0;
function Has_Excluded_Contract return Boolean;
-- Check for contracts that cannot be inlined
- function Has_Excluded_Declaration (Decls : List_Id) return Boolean;
- -- Check for declarations that make inlining not worthwhile
-
- function Has_Excluded_Statement (Stats : List_Id) return Boolean;
- -- Check for statements that make inlining not worthwhile: any
- -- tasking statement, nested at any level. Keep track of total
- -- number of elementary statements, as a measure of acceptable size.
-
function Has_Pending_Instantiation return Boolean;
-- Return True if some enclosing body contains instantiations that
-- appear before the corresponding generic body.
@@ -2046,218 +1894,6 @@ package body Inline is
return False;
end Has_Excluded_Contract;
- ------------------------------
- -- Has_Excluded_Declaration --
- ------------------------------
-
- function Has_Excluded_Declaration (Decls : List_Id) return Boolean is
- D : Node_Id;
-
- function Is_Unchecked_Conversion (D : Node_Id) return Boolean;
- -- Nested subprograms make a given body ineligible for inlining,
- -- but we make an exception for instantiations of unchecked
- -- conversion. The body has not been analyzed yet, so check the
- -- name, and verify that the visible entity with that name is the
- -- predefined unit.
-
- -----------------------------
- -- Is_Unchecked_Conversion --
- -----------------------------
-
- function Is_Unchecked_Conversion (D : Node_Id) return Boolean is
- Id : constant Node_Id := Name (D);
- Conv : Entity_Id;
-
- begin
- if Nkind (Id) = N_Identifier
- and then Chars (Id) = Name_Unchecked_Conversion
- then
- Conv := Current_Entity (Id);
-
- elsif Nkind_In (Id, N_Selected_Component, N_Expanded_Name)
- and then
- Chars (Selector_Name (Id)) = Name_Unchecked_Conversion
- then
- Conv := Current_Entity (Selector_Name (Id));
- else
- return False;
- end if;
-
- return Present (Conv)
- and then Is_Predefined_File_Name
- (Unit_File_Name (Get_Source_Unit (Conv)))
- and then Is_Intrinsic_Subprogram (Conv);
- end Is_Unchecked_Conversion;
-
- -- Start of processing for Has_Excluded_Declaration
-
- begin
- D := First (Decls);
- while Present (D) loop
- if Nkind (D) = N_Function_Instantiation
- and then not Is_Unchecked_Conversion (D)
- then
- Cannot_Inline
- ("cannot inline & (nested function instantiation)?",
- D, Subp);
- return True;
-
- elsif Nkind (D) = N_Protected_Type_Declaration then
- Cannot_Inline
- ("cannot inline & (nested protected type declaration)?",
- D, Subp);
- return True;
-
- elsif Nkind (D) = N_Package_Declaration then
- Cannot_Inline
- ("cannot inline & (nested package declaration)?",
- D, Subp);
- return True;
-
- elsif Nkind (D) = N_Package_Instantiation then
- Cannot_Inline
- ("cannot inline & (nested package instantiation)?",
- D, Subp);
- return True;
-
- elsif Nkind (D) = N_Subprogram_Body then
- Cannot_Inline
- ("cannot inline & (nested subprogram)?",
- D, Subp);
- return True;
-
- elsif Nkind (D) = N_Procedure_Instantiation then
- Cannot_Inline
- ("cannot inline & (nested procedure instantiation)?",
- D, Subp);
- return True;
-
- elsif Nkind (D) = N_Task_Type_Declaration then
- Cannot_Inline
- ("cannot inline & (nested task type declaration)?",
- D, Subp);
- return True;
- end if;
-
- Next (D);
- end loop;
-
- return False;
- end Has_Excluded_Declaration;
-
- ----------------------------
- -- Has_Excluded_Statement --
- ----------------------------
-
- function Has_Excluded_Statement (Stats : List_Id) return Boolean is
- S : Node_Id;
- E : Node_Id;
-
- begin
- S := First (Stats);
- while Present (S) loop
- Stat_Count := Stat_Count + 1;
-
- if Nkind_In (S, N_Abort_Statement,
- N_Asynchronous_Select,
- N_Conditional_Entry_Call,
- N_Delay_Relative_Statement,
- N_Delay_Until_Statement,
- N_Selective_Accept,
- N_Timed_Entry_Call)
- then
- Cannot_Inline
- ("cannot inline & (non-allowed statement)?", S, Subp);
- return True;
-
- elsif Nkind (S) = N_Block_Statement then
- if Present (Declarations (S))
- and then Has_Excluded_Declaration (Declarations (S))
- then
- return True;
-
- elsif Present (Handled_Statement_Sequence (S)) then
- if Present
- (Exception_Handlers (Handled_Statement_Sequence (S)))
- then
- Cannot_Inline
- ("cannot inline& (exception handler)?",
- First (Exception_Handlers
- (Handled_Statement_Sequence (S))),
- Subp);
- return True;
-
- elsif Has_Excluded_Statement
- (Statements (Handled_Statement_Sequence (S)))
- then
- return True;
- end if;
- end if;
-
- elsif Nkind (S) = N_Case_Statement then
- E := First (Alternatives (S));
- while Present (E) loop
- if Has_Excluded_Statement (Statements (E)) then
- return True;
- end if;
-
- Next (E);
- end loop;
-
- elsif Nkind (S) = N_If_Statement then
- if Has_Excluded_Statement (Then_Statements (S)) then
- return True;
- end if;
-
- if Present (Elsif_Parts (S)) then
- E := First (Elsif_Parts (S));
- while Present (E) loop
- if Has_Excluded_Statement (Then_Statements (E)) then
- return True;
- end if;
- Next (E);
- end loop;
- end if;
-
- if Present (Else_Statements (S))
- and then Has_Excluded_Statement (Else_Statements (S))
- then
- return True;
- end if;
-
- elsif Nkind (S) = N_Loop_Statement
- and then Has_Excluded_Statement (Statements (S))
- then
- return True;
-
- elsif Nkind (S) = N_Extended_Return_Statement then
- if Present (Handled_Statement_Sequence (S))
- and then
- Has_Excluded_Statement
- (Statements (Handled_Statement_Sequence (S)))
- then
- return True;
-
- elsif Present (Handled_Statement_Sequence (S))
- and then
- Present (Exception_Handlers
- (Handled_Statement_Sequence (S)))
- then
- Cannot_Inline
- ("cannot inline& (exception handler)?",
- First (Exception_Handlers
- (Handled_Statement_Sequence (S))),
- Subp);
- return True;
- end if;
- end if;
-
- Next (S);
- end loop;
-
- return False;
- end Has_Excluded_Statement;
-
-------------------------------
-- Has_Pending_Instantiation --
-------------------------------
@@ -2513,7 +2149,8 @@ package body Inline is
and then ((Optimization_Level > 0
and then Ekind (Spec_Id) =
E_Function)
- or else Front_End_Inlining));
+ or else Front_End_Inlining
+ or else Back_End_Inlining));
Body_To_Analyze : Node_Id;
@@ -2540,6 +2177,7 @@ package body Inline is
elsif Assertions_Enabled
and then Has_Excluded_Contract
+ and then not Back_End_Inlining
then
return False;
@@ -2563,7 +2201,7 @@ package body Inline is
-- Check excluded declarations
if Present (Declarations (N))
- and then Has_Excluded_Declaration (Declarations (N))
+ and then Has_Excluded_Declaration (Subp, Declarations (N))
then
return False;
end if;
@@ -2581,7 +2219,7 @@ package body Inline is
return False;
elsif Has_Excluded_Statement
- (Statements (Handled_Statement_Sequence (N)))
+ (Subp, Statements (Handled_Statement_Sequence (N)))
then
return False;
end if;
@@ -2595,7 +2233,8 @@ package body Inline is
if Front_End_Inlining
and then
not (Has_Pragma_Inline_Always (Subp) or else GNATprove_Mode)
- and then Stat_Count > Max_Size
+ and then Number_Of_Statements
+ (Statements (Handled_Statement_Sequence (N))) > Max_Size
then
Cannot_Inline ("cannot inline& (body too large)?", N, Subp);
return False;
@@ -2663,8 +2302,23 @@ package body Inline is
return False;
elsif Returns_Unconstrained_Type (Subp) then
- Cannot_Inline
- ("cannot inline & (unconstrained return type)?", N, Subp);
+
+ if Back_End_Inlining
+ and then Can_Split_Unconstrained_Function (N)
+ then
+ return True;
+
+ elsif Has_Single_Return (N) then
+ return True;
+
+ -- Otherwise the secondary stack is involved, and it is not
+ -- worth inlining.
+
+ else
+ Cannot_Inline
+ ("cannot inline & (unconstrained return type)?", N, Subp);
+ end if;
+
return False;
end if;
@@ -2680,7 +2334,7 @@ package body Inline is
-- separately (see Can_Split_Unconstrained_Function).
elsif Returns_Unconstrained_Type (Subp) then
- null;
+ return True;
-- Check supported cases
@@ -3084,7 +2738,7 @@ package body Inline is
Build_Body_To_Inline (N, Spec_Id);
Set_Is_Inlined (Spec_Id);
end if;
- else
+ elsif not Back_End_Inlining then
Build_Body_To_Inline (N, Spec_Id);
Set_Is_Inlined (Spec_Id);
end if;
@@ -3678,14 +3332,14 @@ package body Inline is
-- expanded into a procedure call which must be added after the
-- object declaration.
- if Is_Unc_Decl and then Debug_Flag_Dot_K then
+ if Is_Unc_Decl and then Back_End_Inlining then
Insert_Action_After (Parent (N), Blk);
else
Set_Expression (Parent (N), Empty);
Insert_After (Parent (N), Blk);
end if;
- elsif Is_Unc and then not Debug_Flag_Dot_K then
+ elsif Is_Unc and then not Back_End_Inlining then
Insert_Before (Parent (N), Blk);
end if;
end Rewrite_Function_Call;
@@ -3780,7 +3434,7 @@ package body Inline is
begin
-- Initializations for old/new semantics
- if not Debug_Flag_Dot_K then
+ if not Back_End_Inlining then
Is_Unc := Is_Array_Type (Etype (Subp))
and then not Is_Constrained (Etype (Subp));
Is_Unc_Decl := False;
@@ -3824,7 +3478,7 @@ package body Inline is
and then
Nkind (First (Statements (Handled_Statement_Sequence (Orig_Bod))))
= N_Extended_Return_Statement
- and then not Debug_Flag_Dot_K
+ and then not Back_End_Inlining
then
return;
end if;
@@ -3865,7 +3519,7 @@ package body Inline is
-- Old semantics
- if not Debug_Flag_Dot_K then
+ if not Back_End_Inlining then
declare
Bod : Node_Id;
@@ -4189,7 +3843,7 @@ package body Inline is
-- of the result of a call to an inlined function that returns
-- an unconstrained type
- elsif Debug_Flag_Dot_K
+ elsif Back_End_Inlining
and then Nkind (Parent (N)) = N_Object_Declaration
and then Is_Unc
then
@@ -4429,6 +4083,224 @@ package body Inline is
return Unit;
end Get_Code_Unit_Entity;
+ ------------------------------
+ -- Has_Excluded_Declaration --
+ ------------------------------
+
+ function Has_Excluded_Declaration
+ (Subp : Entity_Id;
+ Decls : List_Id) return Boolean
+ is
+ D : Node_Id;
+
+ function Is_Unchecked_Conversion (D : Node_Id) return Boolean;
+ -- Nested subprograms make a given body ineligible for inlining, but
+ -- we make an exception for instantiations of unchecked conversion.
+ -- The body has not been analyzed yet, so check the name, and verify
+ -- that the visible entity with that name is the predefined unit.
+
+ -----------------------------
+ -- Is_Unchecked_Conversion --
+ -----------------------------
+
+ function Is_Unchecked_Conversion (D : Node_Id) return Boolean is
+ Id : constant Node_Id := Name (D);
+ Conv : Entity_Id;
+
+ begin
+ if Nkind (Id) = N_Identifier
+ and then Chars (Id) = Name_Unchecked_Conversion
+ then
+ Conv := Current_Entity (Id);
+
+ elsif Nkind_In (Id, N_Selected_Component, N_Expanded_Name)
+ and then Chars (Selector_Name (Id)) = Name_Unchecked_Conversion
+ then
+ Conv := Current_Entity (Selector_Name (Id));
+ else
+ return False;
+ end if;
+
+ return Present (Conv)
+ and then Is_Predefined_File_Name
+ (Unit_File_Name (Get_Source_Unit (Conv)))
+ and then Is_Intrinsic_Subprogram (Conv);
+ end Is_Unchecked_Conversion;
+
+ -- Start of processing for Has_Excluded_Declaration
+
+ begin
+ D := First (Decls);
+ while Present (D) loop
+ if Nkind (D) = N_Subprogram_Body then
+ Cannot_Inline
+ ("cannot inline & (nested subprogram)?",
+ D, Subp);
+ return True;
+
+ elsif Nkind (D) = N_Task_Type_Declaration
+ or else Nkind (D) = N_Single_Task_Declaration
+ then
+ Cannot_Inline
+ ("cannot inline & (nested task type declaration)?",
+ D, Subp);
+ return True;
+
+ elsif Nkind (D) = N_Protected_Type_Declaration
+ or else Nkind (D) = N_Single_Protected_Declaration
+ then
+ Cannot_Inline
+ ("cannot inline & (nested protected type declaration)?",
+ D, Subp);
+ return True;
+
+ elsif Nkind (D) = N_Package_Declaration then
+ Cannot_Inline
+ ("cannot inline & (nested package declaration)?",
+ D, Subp);
+ return True;
+
+ elsif Nkind (D) = N_Function_Instantiation
+ and then not Is_Unchecked_Conversion (D)
+ then
+ Cannot_Inline
+ ("cannot inline & (nested function instantiation)?",
+ D, Subp);
+ return True;
+
+ elsif Nkind (D) = N_Procedure_Instantiation then
+ Cannot_Inline
+ ("cannot inline & (nested procedure instantiation)?",
+ D, Subp);
+ return True;
+
+ elsif Nkind (D) = N_Package_Instantiation then
+ Cannot_Inline
+ ("cannot inline & (nested package instantiation)?",
+ D, Subp);
+ return True;
+ end if;
+
+ Next (D);
+ end loop;
+
+ return False;
+ end Has_Excluded_Declaration;
+
+ ----------------------------
+ -- Has_Excluded_Statement --
+ ----------------------------
+
+ function Has_Excluded_Statement
+ (Subp : Entity_Id;
+ Stats : List_Id) return Boolean
+ is
+ S : Node_Id;
+ E : Node_Id;
+
+ begin
+ S := First (Stats);
+ while Present (S) loop
+ if Nkind_In (S, N_Abort_Statement,
+ N_Asynchronous_Select,
+ N_Conditional_Entry_Call,
+ N_Delay_Relative_Statement,
+ N_Delay_Until_Statement,
+ N_Selective_Accept,
+ N_Timed_Entry_Call)
+ then
+ Cannot_Inline
+ ("cannot inline & (non-allowed statement)?", S, Subp);
+ return True;
+
+ elsif Nkind (S) = N_Block_Statement then
+ if Present (Declarations (S))
+ and then Has_Excluded_Declaration (Subp, Declarations (S))
+ then
+ return True;
+
+ elsif Present (Handled_Statement_Sequence (S)) then
+ if Present
+ (Exception_Handlers (Handled_Statement_Sequence (S)))
+ then
+ Cannot_Inline
+ ("cannot inline& (exception handler)?",
+ First (Exception_Handlers
+ (Handled_Statement_Sequence (S))),
+ Subp);
+ return True;
+
+ elsif Has_Excluded_Statement
+ (Subp, Statements (Handled_Statement_Sequence (S)))
+ then
+ return True;
+ end if;
+ end if;
+
+ elsif Nkind (S) = N_Case_Statement then
+ E := First (Alternatives (S));
+ while Present (E) loop
+ if Has_Excluded_Statement (Subp, Statements (E)) then
+ return True;
+ end if;
+
+ Next (E);
+ end loop;
+
+ elsif Nkind (S) = N_If_Statement then
+ if Has_Excluded_Statement (Subp, Then_Statements (S)) then
+ return True;
+ end if;
+
+ if Present (Elsif_Parts (S)) then
+ E := First (Elsif_Parts (S));
+ while Present (E) loop
+ if Has_Excluded_Statement (Subp, Then_Statements (E)) then
+ return True;
+ end if;
+
+ Next (E);
+ end loop;
+ end if;
+
+ if Present (Else_Statements (S))
+ and then Has_Excluded_Statement (Subp, Else_Statements (S))
+ then
+ return True;
+ end if;
+
+ elsif Nkind (S) = N_Loop_Statement
+ and then Has_Excluded_Statement (Subp, Statements (S))
+ then
+ return True;
+
+ elsif Nkind (S) = N_Extended_Return_Statement then
+ if Present (Handled_Statement_Sequence (S))
+ and then
+ Has_Excluded_Statement
+ (Subp, Statements (Handled_Statement_Sequence (S)))
+ then
+ return True;
+
+ elsif Present (Handled_Statement_Sequence (S))
+ and then
+ Present (Exception_Handlers
+ (Handled_Statement_Sequence (S)))
+ then
+ Cannot_Inline
+ ("cannot inline& (exception handler)?",
+ First (Exception_Handlers (Handled_Statement_Sequence (S))),
+ Subp);
+ return True;
+ end if;
+ end if;
+
+ Next (S);
+ end loop;
+
+ return False;
+ end Has_Excluded_Statement;
+
--------------------------
-- Has_Initialized_Type --
--------------------------
@@ -4457,6 +4329,89 @@ package body Inline is
return False;
end Has_Initialized_Type;
+ ------------------------
+ -- Has_Single_Return --
+ ------------------------
+
+ function Has_Single_Return (N : Node_Id) return Boolean is
+ Return_Statement : Node_Id := Empty;
+
+ function Check_Return (N : Node_Id) return Traverse_Result;
+
+ ------------------
+ -- Check_Return --
+ ------------------
+
+ function Check_Return (N : Node_Id) return Traverse_Result is
+ begin
+ if Nkind (N) = N_Simple_Return_Statement then
+ if Present (Expression (N))
+ and then Is_Entity_Name (Expression (N))
+ then
+ if No (Return_Statement) then
+ Return_Statement := N;
+ return OK;
+
+ elsif Chars (Expression (N)) =
+ Chars (Expression (Return_Statement))
+ then
+ return OK;
+
+ else
+ return Abandon;
+ end if;
+
+ -- A return statement within an extended return is a noop
+ -- after inlining.
+
+ elsif No (Expression (N))
+ and then
+ Nkind (Parent (Parent (N))) = N_Extended_Return_Statement
+ then
+ return OK;
+
+ else
+ -- Expression has wrong form
+
+ return Abandon;
+ end if;
+
+ -- We can only inline a build-in-place function if
+ -- it has a single extended return.
+
+ elsif Nkind (N) = N_Extended_Return_Statement then
+ if No (Return_Statement) then
+ Return_Statement := N;
+ return OK;
+
+ else
+ return Abandon;
+ end if;
+
+ else
+ return OK;
+ end if;
+ end Check_Return;
+
+ function Check_All_Returns is new Traverse_Func (Check_Return);
+
+ -- Start of processing for Has_Single_Return
+
+ begin
+ if Check_All_Returns (N) /= OK then
+ return False;
+
+ elsif Nkind (Return_Statement) = N_Extended_Return_Statement then
+ return True;
+
+ else
+ return Present (Declarations (N))
+ and then Present (First (Declarations (N)))
+ and then Chars (Expression (Return_Statement)) =
+ Chars (Defining_Identifier (First (Declarations (N))));
+ end if;
+ end Has_Single_Return;
+
-----------------------------
-- In_Main_Unit_Or_Subunit --
-----------------------------
@@ -4613,6 +4568,24 @@ package body Inline is
Inlined.Release;
end Lock;
+ --------------------------
+ -- Number_Of_Statements --
+ --------------------------
+
+ function Number_Of_Statements (Stats : List_Id) return Natural is
+ Stat_Count : Integer := 0;
+ Stmt : Node_Id;
+
+ begin
+ Stmt := First (Stats);
+ while Present (Stmt) loop
+ Stat_Count := Stat_Count + 1;
+ Next (Stmt);
+ end loop;
+
+ return Stat_Count;
+ end Number_Of_Statements;
+
---------------------------
-- Register_Backend_Call --
---------------------------
diff --git a/gcc/ada/inline.ads b/gcc/ada/inline.ads
index 34720b4..d07a261 100644
--- a/gcc/ada/inline.ads
+++ b/gcc/ada/inline.ads
@@ -132,8 +132,16 @@ package Inline is
Table_Name => "Pending_Descriptor");
Inlined_Calls : Elist_Id := No_Elist;
+ -- List of frontend inlined calls
+
Backend_Calls : Elist_Id := No_Elist;
- -- List of frontend inlined calls and inline calls passed to the backend
+ -- List of inline calls passed to the backend
+
+ Backend_Inlined_Subps : Elist_Id := No_Elist;
+ -- List of subprograms inlined by the backend
+
+ Backend_Not_Inlined_Subps : Elist_Id := No_Elist;
+ -- List of subprograms that cannot be inlined by the backend
-----------------
-- Subprograms --
@@ -231,6 +239,17 @@ package Inline is
-- expressions in the body must be converted to the desired type (which
-- is simply not noted in the tree without inline expansion).
+ function Has_Excluded_Declaration
+ (Subp : Entity_Id;
+ Decls : List_Id) return Boolean;
+ -- Check for declarations that make inlining not worthwhile inlining Subp
+
+ function Has_Excluded_Statement
+ (Subp : Entity_Id;
+ Stats : List_Id) return Boolean;
+ -- Check for statements that make inlining not worthwhile: any tasking
+ -- statement, nested at any level.
+
procedure Register_Backend_Call (N : Node_Id);
-- Append N to the list Backend_Calls
diff --git a/gcc/ada/nlists.ads b/gcc/ada/nlists.ads
index 42c280e..9b73bfe 100644
--- a/gcc/ada/nlists.ads
+++ b/gcc/ada/nlists.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -149,7 +149,6 @@ package Nlists is
-- No_List. (No_List is not considered to be the same as an empty list).
function List_Length (List : List_Id) return Nat;
- pragma Inline (List_Length);
-- Returns number of items in the given list. It is an error to call
-- this function with No_List (No_List is not considered to be the same
-- as an empty list).
diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb
index 09621e7..679518c 100644
--- a/gcc/ada/sem_ch12.adb
+++ b/gcc/ada/sem_ch12.adb
@@ -25,7 +25,6 @@
with Aspects; use Aspects;
with Atree; use Atree;
-with Debug; use Debug;
with Einfo; use Einfo;
with Elists; use Elists;
with Errout; use Errout;
@@ -3877,7 +3876,7 @@ package body Sem_Ch12 is
and then Might_Inline_Subp
and then not Is_Actual_Pack
then
- if not Debug_Flag_Dot_K
+ if not Back_End_Inlining
and then Front_End_Inlining
and then (Is_In_Main_Unit (N)
or else In_Main_Context (Current_Scope))
@@ -3885,7 +3884,7 @@ package body Sem_Ch12 is
then
Inline_Now := True;
- elsif Debug_Flag_Dot_K
+ elsif Back_End_Inlining
and then Must_Inline_Subp
and then (Is_In_Main_Unit (N)
or else In_Main_Context (Current_Scope))
diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb
index cfda659..a2634ac 100644
--- a/gcc/ada/sem_ch3.adb
+++ b/gcc/ada/sem_ch3.adb
@@ -3514,7 +3514,7 @@ package body Sem_Ch3 is
-- declaration without initializing expression and it has been
-- analyzed (see Expand_Inlined_Call).
- if Debug_Flag_Dot_K
+ if Back_End_Inlining
and then Expander_Active
and then Nkind (E) = N_Function_Call
and then Nkind (Name (E)) in N_Has_Entity
diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb
index 9b261d9..b97616b 100644
--- a/gcc/ada/sem_ch6.adb
+++ b/gcc/ada/sem_ch6.adb
@@ -3561,56 +3561,75 @@ package body Sem_Ch6 is
-- mode where we want to expand some calls in place, even with expansion
-- disabled, since the inlining eases formal verification.
- -- Old semantics
+ if not GNATprove_Mode
+ and then Expander_Active
+ and then Serious_Errors_Detected = 0
+ and then Present (Spec_Id)
+ and then Has_Pragma_Inline (Spec_Id)
+ then
+ -- Legacy implementation (relying on frontend inlining)
- if not Debug_Flag_Dot_K then
+ if not Back_End_Inlining then
+ if Has_Pragma_Inline_Always (Spec_Id)
+ or else (Has_Pragma_Inline (Spec_Id) and Front_End_Inlining)
+ then
+ Build_Body_To_Inline (N, Spec_Id);
+ end if;
- -- If the backend inlining is available then at this stage we only
- -- have to mark the subprogram as inlined. The expander will take
- -- care of registering it in the table of subprograms inlined by
- -- the backend a part of processing calls to it (cf. Expand_Call)
+ -- New implementation (relying on backend inlining). Enabled by
+ -- debug flag gnatd.z for testing
- if Present (Spec_Id)
- and then Expander_Active
- and then Back_End_Inlining
- then
- Set_Is_Inlined (Spec_Id);
+ else
+ if Has_Pragma_Inline_Always (Spec_Id)
+ or else Optimization_Level > 0
+ then
+ -- Handle function returning an unconstrained type
- elsif Present (Spec_Id)
- and then Expander_Active
- and then
- (Has_Pragma_Inline_Always (Spec_Id)
- or else (Has_Pragma_Inline (Spec_Id) and Front_End_Inlining))
- then
- Build_Body_To_Inline (N, Spec_Id);
-
- -- In GNATprove mode, inline only when there is a separate subprogram
- -- declaration for now, as inlining of subprogram bodies acting as
- -- declarations, or subprogram stubs, are not supported by frontend
- -- inlining. This inlining should occur after analysis of the body,
- -- so that it is known whether the value of SPARK_Mode applicable to
- -- the body, which can be defined by a pragma inside the body.
-
- elsif GNATprove_Mode
- and then Full_Analysis
- and then not Inside_A_Generic
- and then Present (Spec_Id)
- and then
- Nkind (Parent (Parent (Spec_Id))) = N_Subprogram_Declaration
- and then Can_Be_Inlined_In_GNATprove_Mode (Spec_Id, Body_Id)
- and then not Body_Has_Contract
- then
- Build_Body_To_Inline (N, Spec_Id);
- end if;
+ if Comes_From_Source (Body_Id)
+ and then Ekind (Spec_Id) = E_Function
+ and then Returns_Unconstrained_Type (Spec_Id)
+ then
+ Check_And_Build_Body_To_Inline (N, Spec_Id, Body_Id);
+
+ else
+ declare
+ Body_Spec : constant Node_Id := Parent (Body_Id);
+ Subp_Body : constant Node_Id := Parent (Body_Spec);
+ Subp_Decl : constant List_Id := Declarations (Subp_Body);
- -- New semantics (enabled by debug flag gnatd.k for testing)
+ begin
+ -- Do not pass inlining to the backend if the subprogram
+ -- has declarations or statements which cannot be inlined
+ -- by the backend. This check is done here to emit an
+ -- error instead of the generic warning message reported
+ -- by the GCC backend (ie. "function might not be
+ -- inlinable").
+
+ if Present (Subp_Decl)
+ and then Has_Excluded_Declaration (Spec_Id, Subp_Decl)
+ then
+ null;
- elsif Expander_Active
- and then Serious_Errors_Detected = 0
- and then Present (Spec_Id)
- and then Has_Pragma_Inline (Spec_Id)
- then
- Check_And_Build_Body_To_Inline (N, Spec_Id, Body_Id);
+ elsif Has_Excluded_Statement
+ (Spec_Id,
+ Statements
+ (Handled_Statement_Sequence (Subp_Body)))
+ then
+ null;
+
+ -- If the backend inlining is available then at this
+ -- stage we only have to mark the subprogram as inlined.
+ -- The expander will take care of registering it in the
+ -- table of subprograms inlined by the backend a part of
+ -- processing calls to it (cf. Expand_Call)
+
+ else
+ Set_Is_Inlined (Spec_Id);
+ end if;
+ end;
+ end if;
+ end if;
+ end if;
-- In GNATprove mode, inline only when there is a separate subprogram
-- declaration for now, as inlining of subprogram bodies acting as
@@ -3627,7 +3646,7 @@ package body Sem_Ch6 is
and then Can_Be_Inlined_In_GNATprove_Mode (Spec_Id, Body_Id)
and then not Body_Has_Contract
then
- Check_And_Build_Body_To_Inline (N, Spec_Id, Body_Id);
+ Build_Body_To_Inline (N, Spec_Id);
end if;
-- Ada 2005 (AI-262): In library subprogram bodies, after the analysis
diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb
index 0e899ed..ad64786 100644
--- a/gcc/ada/sem_res.adb
+++ b/gcc/ada/sem_res.adb
@@ -5935,18 +5935,9 @@ package body Sem_Res is
-- check for this by traversing the type in Check_Initialization_Call.
if Is_Inlined (Nam)
- and then Has_Pragma_Inline_Always (Nam)
- and then Nkind (Unit_Declaration_Node (Nam)) = N_Subprogram_Declaration
- and then Present (Body_To_Inline (Unit_Declaration_Node (Nam)))
- and then not Debug_Flag_Dot_K
- then
- null;
-
- elsif Is_Inlined (Nam)
and then Has_Pragma_Inline (Nam)
and then Nkind (Unit_Declaration_Node (Nam)) = N_Subprogram_Declaration
and then Present (Body_To_Inline (Unit_Declaration_Node (Nam)))
- and then Debug_Flag_Dot_K
then
null;