View Issue Details

IDProjectCategoryView StatusLast Update
0038103FPCCompilerpublic2020-11-20 06:35
ReporterOndrej Pokorny Assigned To 
PrioritynormalSeverityminorReproducibilityalways
Status newResolutionopen 
Platformi386-win32 
Product Version3.3.1 
Summary0038103: False "variable uninitialized" compiler warning in boolean evaluation with -O3
DescriptionCompiling with -O3, the following code emits a warning:

// function MyOut(out S: string): Boolean;
if MyOut(S) and (S<>'') then
// Warning: Variable "S" of a managed type does not seem to be initialized

Boolean evaluation is always guaranteed to execute from left to right, therefore S must be initialized after MyOut() execution.
Steps To Reproducecompile the following program with -O3:
fpc OutParamWarning.lpr -O3

program OutParamWarning;
{$mode objfpc}{$H+}
function MyOut(out S: string): Boolean;
begin
  S := 'a';
  Result := True;
end;
var
  S, T: string;
begin
  if MyOut(S) and (S<>'') then // warning: BUG
    Writeln(S);
  MyOut(T);
  Writeln(T); // no warning: OK
end.
Additional InformationCompiling with -O2 does not show the warning.
TagsNo tags attached.
Fixed in Revision
FPCOldBugId
FPCTarget-
Attached Files

Activities

J. Gareth Moreton

2020-11-19 10:07

developer   ~0127043

It looks like it's assuming that S might not get set, which is a safe assumption to make albeit a little annoying. Either way it should probably return the warning in MyOut if that is actually the case.

Ondrej Pokorny

2020-11-19 12:16

developer   ~0127045

> It looks like it's assuming that S might not get set
This is a wrong assumption. That is exactly the difference between OUT and VAR.

The "not initialized" warning for OUT parameters must be done within the subroutine and not outside. After the call the OUT parameter is assumed to be set.

function MyOut(out S: string): Boolean;
begin
  Result := True;
  // 'Warning: Variable "S" of a managed type does not seem to be initialized' - should be shown here
end;

Docs: http://docwiki.embarcadero.com/RADStudio/Sydney/en/Parameters_(Delphi)

Bart Broersma

2020-11-19 16:50

reporter   ~0127050

Also, in the example code S is assigned a value...

J. Gareth Moreton

2020-11-19 17:47

developer   ~0127052

I know S does get set. I was more pointing out the compiler's assumption of assuming S doesn't get set, regardless of what the function does. The compiler is kind of being over-safe, especially as there are constructs where functions don't set out parameters but which are still valid (e.g. returning False if an error occurs and leaving the output parameters undefined).

It's not so straightforward, I don't think, to determine if a function's output parameter is always set and to carry that information to other subroutines that call it.

Ondrej Pokorny

2020-11-20 06:22

developer   ~0127066

You overthink it. The compiler should not carry the information about assignment of the out parameter out of the subroutine. After the subroutine was executed, the out parameter is always assumed to be set.

The check should be executed only within the subroutine.

==> It's the same with the function Result !!!

function MyTest: string;
begin
  if A then
    Result := 'a';
  // warning here
end;

///
  S := MyTest; // no warning here, Result is assumed to be set !!!

Ondrej Pokorny

2020-11-20 06:33

developer   ~0127067

To sum it up: out parameters must behave like function Result values:
1.) After a subroutine with an out parameter was executed, the compiler must assume the out parameter is set, regardless of what the subroutine does.
2.) The assignment check must be done within the subroutine itself, as demonstrated in 0038103:0127045 with a modified MyOut function.

Ondrej Pokorny

2020-11-20 06:35

developer   ~0127068

Last edited: 2020-11-20 06:35

View 2 revisions

> I was more pointing out the compiler's assumption of assuming S doesn't get set, regardless of what the function does. The compiler is kind of being over-safe, especially as there are constructs where functions don't set out parameters but which are still valid (e.g. returning False if an error occurs and leaving the output parameters undefined).

You are wrong. If you were right, the compiler would show a warning also for:
  MyOut(T);
  Writeln(T); // no warning
which it doesn't.

The compiler (wrongly) assumes that in
  if MyOut(S) and (S<>'') then
MyOut doesn't have to be executed.

Issue History

Date Modified Username Field Change
2020-11-19 09:34 Ondrej Pokorny New Issue
2020-11-19 09:35 Ondrej Pokorny Additional Information Updated View Revisions
2020-11-19 09:35 Ondrej Pokorny FPCTarget => -
2020-11-19 09:36 Ondrej Pokorny Description Updated View Revisions
2020-11-19 10:07 J. Gareth Moreton Note Added: 0127043
2020-11-19 12:16 Ondrej Pokorny Note Added: 0127045
2020-11-19 16:50 Bart Broersma Note Added: 0127050
2020-11-19 17:47 J. Gareth Moreton Note Added: 0127052
2020-11-20 06:22 Ondrej Pokorny Note Added: 0127066
2020-11-20 06:33 Ondrej Pokorny Note Added: 0127067
2020-11-20 06:35 Ondrej Pokorny Note Added: 0127068
2020-11-20 06:35 Ondrej Pokorny Note Edited: 0127068 View Revisions