This patch treats expression functions as functions with an implicit pragma Inline_Always. This ensures that they are chained to the list of inlined subprograms of the enclosing unit, and made available to the back end for inlining. The front-end does not examine whether inlining is actually possible because the back end can do this more accurately.
Tested on x86_64-pc-linux-gnu, committed on trunk 2011-08-02 Ed Schonberg <schonb...@adacore.com> * sem_ch6 (Analyze_Expression_Function): treat the function as Inline_Always, and introduce a subprogram declaration for it when it is not a completion. * inline.adb (Add_Inlined_Body): recognize bodies that come from expression functions, so that the back-end can determine whether they can in fact be inlined. * sem_util.adb (Is_Expression_Function): predicate to determine whether a function body comes from an expression function.
Index: inline.adb =================================================================== --- inline.adb (revision 177144) +++ inline.adb (working copy) @@ -6,7 +6,7 @@ -- -- -- B o d y -- -- -- --- Copyright (C) 1992-2010, Free Software Foundation, Inc. -- +-- Copyright (C) 1992-2011, 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- -- @@ -342,7 +342,9 @@ null; elsif not Is_Inlined (Pack) - and then not Has_Completion (E) + and then + (not Has_Completion (E) + or else Is_Expression_Function (E)) then Set_Is_Inlined (Pack); Inlined_Bodies.Increment_Last; Index: sem_util.adb =================================================================== --- sem_util.adb (revision 177153) +++ sem_util.adb (working copy) @@ -6541,6 +6541,26 @@ end if; end Is_Descendent_Of; + ---------------------------- + -- Is_Expression_Function -- + ---------------------------- + + function Is_Expression_Function (Subp : Entity_Id) return Boolean is + Decl : constant Node_Id := Unit_Declaration_Node (Subp); + + begin + return Ekind (Subp) = E_Function + and then Nkind (Decl) = N_Subprogram_Declaration + and then + (Nkind (Original_Node (Decl)) = N_Expression_Function + or else + (Present (Corresponding_Body (Decl)) + and then + Nkind (Original_Node + (Unit_Declaration_Node (Corresponding_Body (Decl)))) + = N_Expression_Function)); + end Is_Expression_Function; + -------------- -- Is_False -- -------------- Index: sem_util.ads =================================================================== --- sem_util.ads (revision 177152) +++ sem_util.ads (working copy) @@ -6,7 +6,7 @@ -- -- -- S p e c -- -- -- --- Copyright (C) 1992-2010, Free Software Foundation, Inc. -- +-- Copyright (C) 1992-2011, 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- -- @@ -741,6 +741,10 @@ -- First determine whether type T is an interface and then check whether -- it is of protected, synchronized or task kind. + function Is_Expression_Function (Subp : Entity_Id) return Boolean; + -- Predicate to determine whether a function entity comes from a rewritten + -- expression function, and should be inlined unconditionally. + function Is_False (U : Uint) return Boolean; pragma Inline (Is_False); -- The argument is a Uint value which is the Boolean'Pos value of a Boolean Index: sem_ch6.adb =================================================================== --- sem_ch6.adb (revision 177172) +++ sem_ch6.adb (working copy) @@ -271,6 +271,7 @@ LocX : constant Source_Ptr := Sloc (Expression (N)); Def_Id : constant Entity_Id := Defining_Entity (Specification (N)); New_Body : Node_Id; + New_Decl : Node_Id; Prev : constant Entity_Id := Current_Entity_In_Scope (Def_Id); -- If the expression is a completion, Prev is the entity whose @@ -278,9 +279,14 @@ begin -- This is one of the occasions on which we transform the tree during - -- semantic analysis. Transform the expression function into an - -- equivalent subprogram body, and then analyze that. + -- semantic analysis. If this is a completion, transform the expression + -- function into an equivalent subprogram body, and analyze it. + -- Expression functions are inlined unconditionally. The back-end will + -- determine whether this is possible. + + Inline_Processing_Required := True; + New_Body := Make_Subprogram_Body (Loc, Specification => Specification (N), @@ -304,10 +310,37 @@ Rewrite (N, Make_Null_Statement (Loc)); Analyze (N); Analyze (New_Body); + Set_Is_Inlined (Prev); - else + elsif Present (Prev) then Rewrite (N, New_Body); + Set_Is_Inlined (Prev); Analyze (N); + + -- If this is not a completion, create both a declaration and a body, + -- so that the expression can be inlined whenever possible. + + else + New_Decl := + Make_Subprogram_Declaration (Loc, + Specification => Specification (N)); + Rewrite (N, New_Decl); + Analyze (N); + Set_Is_Inlined (Defining_Entity (New_Decl)); + + -- Create new set of formals for specification in body. + + Set_Specification (New_Body, + Make_Function_Specification (Loc, + Defining_Unit_Name => + Make_Defining_Identifier (Loc, Chars (Defining_Entity (N))), + Parameter_Specifications => + Copy_Parameter_List (Defining_Entity (New_Decl)), + Result_Definition => + New_Copy_Tree (Result_Definition (Specification (New_Decl))))); + + Insert_After (N, New_Body); + Analyze (New_Body); end if; end Analyze_Expression_Function;