Saturday, April 25, 2015

Value Never Used – Or Is It?

Sometimes, dcc32 is just plain stupid …

I have this code in the OmniThreadLibrary:

function TOmniThreadPool.Cancel(taskID: int64): boolean;
var
res: TOmniWaitableValue;
begin
{$IF CompilerVersion >= 22}
Result := false; // not really used
{$IFEND}
res := TOmniWaitableValue.Create;
try
otpWorkerTask.Invoke(@TOTPWorker.Cancel, [taskID, res]);
res.WaitFor(INFINITE);
Result := res.Value;
finally FreeAndNil(res); end;
end
;

The IFDEF part is there because otherwise compiler complains about result being potentially undefined.


[DCC Warning] OtlThreadPool.pas(1315): W1035 Return value of function 'TOmniThreadPool.Cancel' might be undefined


I’ve first observed this with the XE and it was fixed after the XE2 (can’t repeat this with XE8, but I didn’t check every compiler inbetween.)



There’s trouble with this dirty fix, though. If code inlining is disabled (Options, Delphi Compiler, Compiling, Code generation, Code inlining control = Off), I get a hint on the Result := false assignment.


[DCC Hint] OtlThreadPool.pas(1307): H2077 Value assigned to 'TOmniThreadPool.Cancel' never used


I’ve minimized the problem down to this (you’ll still need few OTL units to compile it):

program ProjectValueUndefined;

{$APPTYPE CONSOLE}

{$R *.res}

uses
System.SysUtils,
OtlCommon;

type
TValueWrapper = class
FValue: TOmniValue;
property Value: TOmniValue read FValue;
end;

function Cancel: integer;
var
res: TValueWrapper;
begin
res := TValueWrapper.Create;
try
Result := res.Value;
finally FreeAndNil(res); end;
end;

begin
end
.

The problem seems to lie in TOmniValue.Implicit(TOmniValue): boolean, which is marked ‘inline’. If I remove that ‘'inline’, compiler stops misbehaving. That would, however, be a bad solution as this inlining rather significantly speeds up working with the TOmniValue record. (Plus I would have to do it for other types, not just boolean, as the error can equally well be reproduced if I change the result of the Cancel function to ‘integer’.)


So I’m looking for a way that would remove this stupid hint and which would not introduce any other warnings/hints when inlining is off. Sadly, {$IFOPT INLINE} is not supported as I would use that hack.


If you have any idea about what may work – even if you can’t test it – please post it in comments. Thanks!

2 comments:

  1. Anonymous17:26

    This is stupid, but should do the trick
    Result := False;
    if not Result then
    begin
    rest of the function
    end.

    ReplyDelete
    Replies
    1. Good one :)

      I'm currently just wrapping this code in {$WARN NO_RETVAL OFF}/{$WARN NO_RETVAL ON}, as suggested on Google+.

      Delete