[fpc-devel] Wrong docs: not initialized global variables
Ondrej Pokorny
lazarus at kluug.net
Sat Jul 7 12:11:44 CEST 2018
On 07.07.2018 10:54, Florian Klämpfl wrote:
> Am 07.07.2018 um 08:18 schrieb Ondrej Pokorny:
>>
>> As you see, all messages are hints only, no warnings. Regardless of
>> managed/not-managed global/local variable.
>>
>
> There are a lot of exceptions when which warning happens, try the same
> with e.g. writeln and the file parameter (just one of these exceptions).
"A lot of exceptions" doesn't look like very systematic, logical and
orthogonal in the first place.
> SetLength is a case were a warning is valid because it can result in
> very bogus results (as this thread has shown).
I think you mean the "[fpc-devel] Managed Types, Undefined Bhaviour" thread.
"it can result in very bogus results" only in combination with the
special Result function variable. Never with a local or global variable
because they are guaranteed to be niled/zeroed (SetLength can be used on
managed types only). Therefore the warning would make sense only in
combination with function Result if your argument is used. With
local/global variable the warning is not valid because it can NOT result
in bogus results.
This applies to every other routine that takes a var parameter, not only
SetLength. I don't understand why SetLength should be special. See the
code below:
program Project1;
type
Vector = array of integer;
procedure DoSetLength(var V: Vector; len: Integer);
begin
SetLength(V, 4);
end;
function DoSomething1 (len: Integer): Vector;
begin
DoSetLength(Result, len); // << HINT
end;
function DoSomething2 (len: Integer): Vector;
begin
SetLength(Result, len); // << WARNING
end;
type
TFoo = class
A, B: Vector;
end;
procedure Main;
var
foo: TFoo;
begin
foo := TFoo.Create;
foo.A := DoSomething1(3); // try DoSomething2
foo.A[0] := 42;
foo.B := DoSomething1(4); // try DoSomething2
Writeln(foo.B[0]);
end;
begin
Main;
Readln;
end.
Both DoSomething1 and DoSomething2 produce the same bogus code and yet
you decided that DoSomething1 deserves a hint and DoSomething2 deserves
a warning.
Earlier in this thread you wrote:
On 03.07.2018 20:54, Florian Klämpfl wrote:
> The warning happens also for any other call which takes an
> uninitialized variable as var parameter (see e.g. fillchar). So the
> warning increases only orthogonality of the language.
Which is not true because "any other call which takes an uninitialized
variable as var parameter (see e.g. fillchar)" shows a hint only, not a
warning:
procedure DoSomething;
var
O, P: string;
begin
SetLength(O, 1); // << Warning
FillChar(P, 1, 0); // << Hint
end;
I ask myself where is the orthogonality you wrote about?
On 07.07.2018 10:44, Florian Klämpfl wrote:
> Am 07.07.2018 um 08:05 schrieb Ondrej Pokorny:
>> makes me feel I have been always right in this thread...
>
> Fine, so we can close the case.
I agree. I officially stop trying to show you inconsistencies in your
documentation and the compiler message system.
I find it ironic that you use arguments for the current state of
documentation and compiler message system that - if you actually prove
them - show exactly the inconsistencies I point to and are against the
current state of documentation and compiler message system.
-----
Already in March/April this year I tried to convince the FPC team in
this thread that the rules for warning/hint of initialized variables
should be changed and that some warnings should be downgraded to notes.
Jonas always replied with a disapproval.
Let me sum up my POV the last time:
throw a WARNING: if bogus results can happen.
throw a HINT: if bogus results can NOT happen.
You have then these 4 categories:
- uninitialized unmanaged+managed Result variable: bogus => WARNING
- uninitialized local unmanaged variable (ordinals etc): bogus => WARNING
- uninitialized local managed variable (strings etc): OK => NOTE
- uninitialized unmanaged+managed global variable: OK => NOTE
Especially you may not differentiate how the variable is used
(right-side of the assignment, SetLength, other routine with var
parameter etc.).
The current state is a strange mix of exceptions and rules that are
irrational and not orthogonal.
To demonstrate my POV I made a small program that shows the current
state and my POV:
program Project1;
uses StrUtils;
procedure DoVar(var S: string);
begin
S := S + S;
end;
procedure DoVar(var O: Integer);
begin
O := O + O;
end;
procedure Main;
var
S1, S2, S3: string;
O1, O2: string;
begin
S1 := S1 + S1; // << warning, should be: note (WRONG)
SetLength(S2, 0); // << warning, should be: note (WRONG)
DoVar(S3); // << note, should be: note (OK)
O1 := O1 + O1; // << warning, should be: warning (OK)
DoVar(O2); // << note, should be: warning (WRONG)
end;
function M1: string;
begin
Result := Result + Result; // << warning, should be: warning (OK)
end;
function M2: string;
begin
SetLength(Result, 0); // << warning, should be: warning (OK)
end;
function M3: string;
begin
DoVar(Result); // << note, should be: warning (WRONG)
end;
function U1: Integer;
begin
Result := Result + Result; // << warning, should be: warning (OK)
end;
function U2: Integer;
begin
DoVar(Result); // << note, should be: warning (WRONG)
end;
var
GS1, GS2, GS3: string;
GO1, GO2: string;
begin
GS1 := GS1 + GS1; // << warning, should be: note (WRONG)
SetLength(GS2, 0); // << warning, should be: note (WRONG)
DoVar(GS3); // << note, should be: note (OK)
GO1 := GO1 + GO1; // << warning, should be: note (WRONG)
DoVar(GO2); // << note, should be: note (OK)
end.
This should be the basis without any (additional) exceptions.
(The exceptions I wrote before like SetLength/FillChar being ignored for
compiler messages etc. are still valid from the programmer's POV but
don't have to be applied to keep the system simple and "orthogonal".)
Ondrej
More information about the fpc-devel
mailing list