Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2011-11

Internal error in FPC 2.6.0rc1

11 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Michael Müller

Hi,

I tested RC1 using one of my codes and ran into an internal error. I was able to reduce the code to the following.

Free Pascal Compiler version 2.6.0rc1 [2011/10/15] for i386 Copyright (c) 1993-2011 by Florian Klaempfl and others Target OS: Win32 for i386
Compiling InternalError.dpr
InternalError.dpr(21,3) Fatal: Internal error 201103063 Fatal: Compilation aborted

--- Code, start ---

{$IFDEF FPC}
  {$MODE Delphi}
{$ENDIF}
program InternalError;
procedure SetArray({var}out SingleArray: array of Single; const Value: Single);
var
  I: Integer;
begin
  for I := Low(SingleArray) to High(SingleArray) do
    SingleArray[I] := Value;
end;
var
  ValuesBuffer: array of Single;
begin
  SetLength(ValuesBuffer, 5);
  SetArray(ValuesBuffer, 5.7);
end.

--- Code, end ---

The error is at the beginning of SetArray() call.

I see that the real error is in my code since the procedure parameter has to be 'var' and not 'out' otherwise the dimension which is set outside will not reach the procedure. But the compiler shouldn't stop with an internal error. If it is changed to 'var' it compiles.

FPC 2.4.4 just compiles it.

Regards

Michael

Reply by email

Sergei Gorelkin
to Michael Müller

25.11.2011 13:36, Michael Müller пишет:

Show quoted text 39 lines
Hi, I tested RC1 using one of my codes and ran into an internal error. I was able to reduce the code to the following. Free Pascal Compiler version 2.6.0rc1 [2011/10/15] for i386 Copyright (c) 1993-2011 by Florian Klaempfl and others Target OS: Win32 for i386 Compiling InternalError.dpr InternalError.dpr(21,3) Fatal: Internal error 201103063 Fatal: Compilation aborted --- Code, start --- {$IFDEF FPC} {$MODE Delphi} {$ENDIF} program InternalError; procedure SetArray({var}out SingleArray: array of Single; const Value: Single); var I: Integer; begin for I := Low(SingleArray) to High(SingleArray) do SingleArray[I] := Value; end; var ValuesBuffer: array of Single; begin SetLength(ValuesBuffer, 5); SetArray(ValuesBuffer, 5.7); end. --- Code, end --- The error is at the beginning of SetArray() call.

I guess this one is for me to fix.

I see that the real error is in my code since the procedure parameter has to be 'var' and not 'out' otherwise the dimension which is set outside will not reach the procedure. But the compiler shouldn't stop with an internal error. If it is changed to 'var' it compiles.

Frankly speaking, I doubt that. 'out' in this case likely refers to elements of dynamic array, not to array itself. If it was e.g. 'array of ansistring' then all its elements should be finalized before the call, then pointer to first element and length passed to callee.

FPC 2.4.4 just compiles it.

But it may produce incorrect code when managed types are involved, see http://bugs.freepascal.org/view.php?id=18859

Regards,
Sergei

Reply by email

Sergei Gorelkin
to Sergei Gorelkin

25.11.2011 15:49, Sergei Gorelkin пишет:

Show quoted text 5 lines
> > The error is at the beginning of SetArray() call. > I guess this one is for me to fix.

Fixed in r19684.
If possible, please consider merging the fix to 2.6.

Regards,
Sergei

Reply by email

Michael Müller
to Sergei Gorelkin: 25.11.2011 13:36, Michael Müller пишет: I guess this one is for me to fix. Frankly…

Hi Sergei

Sergei Gorelkin wrote 41 lines
25.11.2011 13:36, Michael Müller пишет: > Hi, > > I tested RC1 using one of my codes and ran into an internal error. I was able to reduce the code to the following. > > Free Pascal Compiler version 2.6.0rc1 [2011/10/15] for i386 > Copyright (c) 1993-2011 by Florian Klaempfl and others > Target OS: Win32 for i386 > Compiling InternalError.dpr > InternalError.dpr(21,3) Fatal: Internal error 201103063 > Fatal: Compilation aborted > > --- Code, start --- > > {$IFDEF FPC} > {$MODE Delphi} > {$ENDIF} > > program InternalError; > > procedure SetArray({var}out SingleArray: array of Single; const Value: Single); > var > I: Integer; > begin > for I := Low(SingleArray) to High(SingleArray) do > SingleArray[I] := Value; > end; > > var > ValuesBuffer: array of Single; > > begin > SetLength(ValuesBuffer, 5); > SetArray(ValuesBuffer, 5.7); > end. > > --- Code, end --- > > The error is at the beginning of SetArray() call. > I guess this one is for me to fix.

Thanks for the fix. Hopefully it finds it way into 2.6.

> I see that the real error is in my code since the procedure parameter has to be 'var' and not 'out' otherwise the dimension which is set outside will not reach the procedure. But the compiler shouldn't stop with an internal error. If it is changed to 'var' it compiles. > Frankly speaking, I doubt that. 'out' in this case likely refers to elements of dynamic array, not to array itself. If it was e.g. 'array of ansistring' then all its elements should be finalized before the call, then pointer to first element and length passed to callee.

After your statement I played a little bit and it seems that you are right. When using 'out' the length of the array reaches the procedure. But what surprises me much more is that even values of the array reach the procedure. I added a loop at the beginning of the procedure that print the array before the (new) value is set and it shows the values that were set outside the procedure after SetLength(). For an array of String the elements are emptied (as you stated too). Does this mean that reference counted elements are emptied and the others not? Beside that what is than the difference between 'out' and 'var'? (I tested this also with Delphi 2009 with exact the same behaviour). The Delphi help mentions that for 'out' parameters the referenced variable is freed (or so) when it is given to the routine (I have only a German help otherwise I would show the text here). This is exact the behaviour that I expected. So for me it sounds that even Delphi is not doing it as stated in the documentation. Where is my understanding wrong here?

Regards

Michael

Reply by email

Jonas Maebe
to Michael Müller
Michael Müller wrote
Does this mean that reference counted elements are emptied and the others not?

Yes.

Beside that what is than the difference between 'out' and 'var'?

If you enable hints, the compiler will print a hint if it detects you passing a potentially uninitialized variable to a "var" parameter, while it won't print such a warning if you pass it to an "out" parameter. Additionally, if you use the -gt command line option then the compiler will overwrite the contents of (non-reference-counted) out-parameters in the function entry code. This switch will do nothing for open array parameters though, because it lacks support for using the hidden "high" parameter to determine the bounds of the array at run time.

Jonas

Reply by email

Michael Müller
to Jonas Maebe
Jonas Maebe wrote 6 lines
On 28 Nov 2011, at 00:49, Michael Müller wrote: > Beside that what is than the difference between 'out' and 'var'? If you enable hints, the compiler will print a hint if it detects you passing a potentially uninitialized variable to a "var" parameter, while it won't print such a warning if you pass it to an "out" parameter.

But inside the routine with "out" parameter I had expected to get the same warning ;-). But this was before I learnt that at least something of an "out" parameter reaches the routine.

Why is this 'passing a potentially uninitialized variable to a "var" parameter' ('bla does not seem to be initialized') message a warning for arrays and a hint for basic types?

Additionally, if you use the -gt command line option then the compiler will overwrite the contents of (non-reference-counted) out-parameters in the function entry code. This switch will do nothing for open array parameters though, because it lacks support for using the hidden "high" parameter to determine the bounds of the array at run time.

I don't understand this restriction. In the code High() works for open arrays at run time.

Regards

Michael

Reply by email

Sven Barth
to Michael Müller
Michael Müller wrote
> Additionally, if you use the -gt command line option then the compiler will overwrite the contents of (non-reference-counted) out-parameters in the function entry code. This switch will do nothing for open array parameters though, because it lacks support for using the hidden "high" parameter to determine the bounds of the array at run time. I don't understand this restriction. In the code High() works for open arrays at run time.

I suppose that the "-gt" code is generated on a lower level, so it can't just use High(), but would need to access the hidden parameter that contains the array length directly. And that part is simply not implemented, so open arrays are not handled.

Regards,
Sven

Reply by email

Jonas Maebe
to Michael Müller: But inside the routine with "out" parameter I had expected to get the same warning ;-).…
Michael Müller wrote 9 lines
Am 28.11.2011 um 01:05 schrieb Jonas Maebe: > If you enable hints, the compiler will print a hint if it detects > you passing a potentially uninitialized variable to a "var" > parameter, while it won't print such a warning if you pass it to an > "out" parameter. But inside the routine with "out" parameter I had expected to get the same warning ;-).

You do get a warning if you use an "out" parameter inside a routine without first writing to it.

Why is this 'passing a potentially uninitialized variable to a "var" parameter' ('bla does not seem to be initialized') message a warning for arrays and a hint for basic types?

It's only a warning for dynamic arrays. And the cause is a side effect of the way a "dynamic array" is internally converted to an "open array". It shouldn't be very difficult to fix that though.

I don't understand this restriction. In the code High() works for open arrays at run time.

See Sven's answer.

Jonas

Reply by email

Sergei Gorelkin
to Sven Barth: I suppose that the "-gt" code is generated on a lower level, so it can't just use High(),…

28.11.2011 14:26, Sven Barth пишет:

Show quoted text 12 lines
Am 28.11.2011 12:02, schrieb Michael Müller: >> Additionally, if you use the -gt command line option then the compiler will overwrite the >> contents of (non-reference-counted) out-parameters in the function entry code. This switch will >> do nothing for open array parameters though, because it lacks support for using the hidden "high" >> parameter to determine the bounds of the array at run time. > > I don't understand this restriction. In the code High() works for open arrays at run time. I suppose that the "-gt" code is generated on a lower level, so it can't just use High(), but would need to access the hidden parameter that contains the array length directly. And that part is simply not implemented, so open arrays are not handled.

Yes, this is simply an unimplemented feature.

Sergei

Reply by email

Michael Müller
to Jonas Maebe: You do get a warning if you use an "out" parameter inside a routine without first writing…
Jonas Maebe wrote 10 lines
On 28 Nov 2011, at 12:02, Michael Müller wrote: > Am 28.11.2011 um 01:05 schrieb Jonas Maebe: > >> If you enable hints, the compiler will print a hint if it detects you passing a potentially uninitialized variable to a "var" parameter, while it won't print such a warning if you pass it to an "out" parameter. > > But inside the routine with "out" parameter I had expected to get the same warning ;-). You do get a warning if you use an "out" parameter inside a routine without first writing to it.
But only if you try to access an array element. I would have expected to get such a warning also when using Length(), Low() or High() (which I did in my original example). But I assume this difference is coming from how an array is handled. Even without using SetLength() I assume that just by declaring an array variable there is an internal structure that contains the array length field and the pointer to the element block. And there is no possibility to differ between an uninitialized (since initialized internally) and a SetLength(, 0) or array := nil. Is this correct?

Regards

Michael

Reply by email

Jonas Maebe
to Michael Müller
Michael Müller wrote 10 lines
Am 28.11.2011 um 13:12 schrieb Jonas Maebe: > You do get a warning if you use an "out" parameter inside a routine > without first writing to it. But only if you try to access an array element. I would have expected to get such a warning also when using Length(), Low() or High() (which I did in my original example). But I assume this difference is coming from how an array is handled.

Probably, yes. The checks for uninitialized values in FPC is are quite ad hoc en very much based on "best effort" rather than on any kind of guarantees.

Show quoted text 6 lines
Even without using SetLength() I assume that just by declaring an array variable there is an internal structure that contains the array length field and the pointer to the element block. And there is no possibility to differ between an uninitialized (since initialized internally) and a SetLength(, 0) or array := nil. Is this correct?

No. The compiler does not take into internal initializations for "uninitialized" checks.

Jonas

Reply by email