Compiler Hint: “Inline function '…' has not been expanded…”

后端 未结 4 1163
难免孤独
难免孤独 2021-02-19 05:06

In a unit I use the function DeleteFile and the compiler outputs a hint:

\"H2443 Inline function \'DeleteFile\' has not been expanded because

相关标签:
4条回答
  • 2021-02-19 05:51

    I was also confused by this hint. Then i realized what the issue is. Your code:

    uses
       SysUtils;
    
    procedure TForm1.DoStuff;
    begin
       SysUtils.DeleteFile('foo');
    end;
    

    is literally being replaced with:

    uses
       SysUtils;
    
    procedure TForm1.DoStuff;
    var
      Flags, LastError: Cardinal;
    begin
      Result := Winapi.Windows.DeleteFile(PChar(FileName));
    
      if not Result then
      begin
        LastError := GetLastError;
        Flags := GetFileAttributes(PChar(FileName));
    
        if (Flags <> INVALID_FILE_ATTRIBUTES) and (faSymLink and Flags <> 0) and
          (faDirectory and Flags <> 0) then
        begin
          Result := RemoveDirectory(PChar(FileName));
          Exit;
        end;
    
        SetLastError(LastError);
      end;
    end;
    

    If you'll notice, your "new" code depends on WinApi.Windows unit:

    Result := Winapi.Windows.DeleteFile(PChar(FileName));
    

    which you didn't include in your uses clause.

    If you manually had inlined the code (copied and pasted), the code would simply not compile until you added Windows to your uses.

    Instead, the compiler will not do the inline because:

    Inline function 'DeleteFile' has not been expanded because unit 'Windows' is not specified in USES list"

    0 讨论(0)
  • 2021-02-19 06:01

    It's an inlining restriction.

    See Hallvard Vassbotn's article about Inlined Routines.

    Extracted from that site:

    The rest of the inlining restrictions are common for both platforms and the most important ones are

    • no inlining across package boundaries
    • the inlined routine cannot access implementation section identifiers
    • the call site must have access to all identifiers used in the inlined routine

    Note The last point means that unless the call site unit uses the units required by the routine, the routine cannot be inlined. When this happens, the compiler emits a hint like this

     [Pascal Hint] InlinedRoutinesU.pas(14): H2443 Inline function 
       'InlineMe' has not been expanded because unit 'RequiredUnit' 
        is not specified in USES list 
    

    To resolve the issue, add the missing unit name to the call site's uses clause.

    0 讨论(0)
  • 2021-02-19 06:04

    Inline functions can be expanded inline. For example:

    function AddPlus(const A,B: Integer): Integer; inline;
    begin
      Result := A + B + 1;
    end;
    
    var
      x,y,z : Integer;
    begin
      y := 22;
      z := 11;
      x := AddPlus(y, z);
    end.
    

    Is rewritten to:

    var
      x,y,z : Integer;
    begin
      y := 22;
      z := 11;
      x := y+z+1;
    end.
    

    This removes the overhead of a function call.

    But in order to replace the call with the function body, the compiler needs more information, hence the complaint about the unit.

    Beware that not all inline functions are converted. Some are treated just like normal functions (its up to the compiler). Besides, inline is only needed at really tight performance bottlenecks.

    0 讨论(0)
  • 2021-02-19 06:06

    Inline functions are expanded in place by the compiler, avoiding the overhead of a function call. E.g. for squaring, sqr(x) is compiled in as x*x rather than calling a function that multiplies x and returns the result.

    0 讨论(0)
提交回复
热议问题