View Issue Details

IDProjectCategoryView StatusLast Update
0035576FPCRTLpublic2019-05-27 09:20
ReporterPascal RiekenbergAssigned ToMichael Van Canneyt 
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionfixed 
Platformi386OSWindows 10 x64OS Version1809
Product Version3.3.1Product Build42049 
Target VersionFixed in Version 
Summary0035576: r42042-r42049 prevent Lazarus (i386) from starting
DescriptionSome changes between r42042 and r42049 prevent Lazarus (32bit, Windows) from startting:

[FORMS.PP] ExceptionOccurred
  Sender=EInvalidGraphic
  Exception=Stream is not an Icon type
  Stack trace:
  $005410B7 TCUSTOMICON__READSTREAM, line 828 of ./include/icon.inc
  $00531AD7 TRASTERIMAGE__LOADFROMSTREAM, line 441 of ./include/rasterimage.inc
  $00532CA0 TRASTERIMAGE__READDATA, line 913 of ./include/rasterimage.inc
  $00540F7B TCUSTOMICON__READDATA, line 800 of ./include/icon.inc
  $005431A5 TICON__LOADFROMRESOURCEHANDLE, line 1435 of ./include/icon.inc
  $00448C57 TAPPLICATION__INITIALIZE, line 463 of ./include/application.inc
  $0040378D main, line 132 of lazarus.pp
TApplication.HandleException: EInvalidGraphic
Stream is not an Icon type
  Stack trace:
  $005410B7 TCUSTOMICON__READSTREAM, line 828 of ./include/icon.inc
  $00531AD7 TRASTERIMAGE__LOADFROMSTREAM, line 441 of ./include/rasterimage.inc
  $00532CA0 TRASTERIMAGE__READDATA, line 913 of ./include/rasterimage.inc
  $00540F7B TCUSTOMICON__READDATA, line 800 of ./include/icon.inc
  $005431A5 TICON__LOADFROMRESOURCEHANDLE, line 1435 of ./include/icon.inc
  $00448C57 TAPPLICATION__INITIALIZE, line 463 of ./include/application.inc
  $0040378D main, line 132 of lazarus.pp
TagsNo tags attached.
Fixed in Revision42057, 42118
FPCOldBugId
FPCTarget-
Attached Files
  • Error.png (5,725 bytes)
    Error.png (5,725 bytes)
  • classes_TStream_35576.patch (2,743 bytes)
    Index: rtl/objpas/classes/classesh.inc
    ===================================================================
    --- rtl/objpas/classes/classesh.inc	(revision 42056)
    +++ rtl/objpas/classes/classesh.inc	(working copy)
    @@ -900,8 +900,8 @@
         Procedure WriteExactSizeData(Const Buffer; aSize,aCount : NativeInt);
       public
         function Read(var Buffer; Count: Longint): Longint; virtual;
    -    function Read(Buffer: TBytes; Count: Longint): Longint; overload;
    -    function Read(Buffer : TBytes; aOffset, Count: Longint): Longint; overload;
    +    function Read(var Buffer: TBytes; Count: Longint): Longint; overload;
    +    function Read(var Buffer: TBytes; aOffset, Count: Longint): Longint; overload;
     
         function Write(const Buffer: TBytes; Offset, Count: Longint): Longint; overload;
         function Write(const Buffer: TBytes; Count: Longint): Longint; overload;
    @@ -910,8 +910,8 @@
         function Seek(Offset: Longint; Origin: Word): Longint; virtual; overload;
         function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; virtual; overload;
     
    -    function ReadData(Buffer: Pointer; Count: NativeInt): NativeInt; overload;
    -    function ReadData(const Buffer: TBytes; Count: NativeInt): NativeInt; overload;
    +    function ReadData(var Buffer: Pointer; Count: NativeInt): NativeInt; overload;
    +    function ReadData(var Buffer: TBytes; Count: NativeInt): NativeInt; overload;
         function ReadData(var Buffer: Boolean): NativeInt; overload;
         function ReadData(var Buffer: Boolean; Count: NativeInt): NativeInt; overload;
         function ReadData(var Buffer: AnsiChar): NativeInt; overload;
    Index: rtl/objpas/classes/streams.inc
    ===================================================================
    --- rtl/objpas/classes/streams.inc	(revision 42056)
    +++ rtl/objpas/classes/streams.inc	(working copy)
    @@ -30,12 +30,12 @@
       Result := 0;
     end;
     
    -function TStream.Read(Buffer: TBytes; Count: Longint): Longint;
    +function TStream.Read(var Buffer: TBytes; Count: Longint): Longint;
     begin
       Result:=Read(Buffer,0,Count);
     end;
     
    -function TStream.Read(Buffer: TBytes; aOffset, Count: Longint): Longint;
    +function TStream.Read(var Buffer: TBytes; aOffset, Count: Longint): Longint;
     begin
       Result:=Read(Buffer[aOffset],Count);
     end;
    @@ -198,12 +198,12 @@
           Result:=Seek(longint(Offset),ord(Origin));
         end;
     
    - function TStream.ReadData(Buffer: Pointer; Count: NativeInt): NativeInt;
    + function TStream.ReadData(var Buffer: Pointer; Count: NativeInt): NativeInt;
      begin
        Result:=Read(Buffer^,Count);
      end;
     
    - function TStream.ReadData(const Buffer: TBytes; Count: NativeInt): NativeInt;
    + function TStream.ReadData(var Buffer: TBytes; Count: NativeInt): NativeInt;
      begin
        Result:=Read(Buffer,0,Count);
      end;
    
  • Unbenannt.png (8,552 bytes)
    Unbenannt.png (8,552 bytes)
  • readbuffer-var.patch (2,046 bytes)
    Index: rtl/objpas/classes/classesh.inc
    ===================================================================
    --- rtl/objpas/classes/classesh.inc	(revision 42061)
    +++ rtl/objpas/classes/classesh.inc	(working copy)
    @@ -901,7 +901,7 @@
       public
         function Read(var Buffer; Count: Longint): Longint; virtual; overload;
         function Read(var Buffer: TBytes; Count: Longint): Longint; overload;
    -    function Read( Buffer : TBytes; aOffset, Count: Longint): Longint; overload;
    +    function Read(var Buffer: TBytes; aOffset, Count: Longint): Longint; overload;
     
         function Write(const Buffer: TBytes; Offset, Count: Longint): Longint; overload;
         function Write(const Buffer: TBytes; Count: Longint): Longint; overload;
    @@ -911,7 +911,7 @@
         function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; virtual; overload;
     
         function ReadData(Buffer: Pointer; Count: NativeInt): NativeInt; overload;
    -    function ReadData(Buffer: TBytes; Count: NativeInt): NativeInt; overload;
    +    function ReadData(var Buffer: TBytes; Count: NativeInt): NativeInt; overload;
         function ReadData(var Buffer: Boolean): NativeInt; overload;
         function ReadData(var Buffer: Boolean; Count: NativeInt): NativeInt; overload;
         function ReadData(var Buffer: AnsiChar): NativeInt; overload;
    Index: rtl/objpas/classes/streams.inc
    ===================================================================
    --- rtl/objpas/classes/streams.inc	(revision 42061)
    +++ rtl/objpas/classes/streams.inc	(working copy)
    @@ -35,7 +35,7 @@
       Result:=Read(Buffer,0,Count);
     end;
     
    -function TStream.Read(Buffer: TBytes; aOffset, Count: Longint): Longint;
    +function TStream.Read(var Buffer: TBytes; aOffset, Count: Longint): Longint;
     begin
       Result:=Read(Buffer[aOffset],Count);
     end;
    @@ -203,7 +203,7 @@
        Result:=Read(Buffer^,Count);
      end;
     
    - function TStream.ReadData({var} Buffer: TBytes; Count: NativeInt): NativeInt;
    + function TStream.ReadData(var Buffer: TBytes; Count: NativeInt): NativeInt;
      begin
        Result:=Read(Buffer,0,Count);
      end;
    
    readbuffer-var.patch (2,046 bytes)

Relationships

related to 0035580 closedJonas Maebe Compiler picks up wrong overload for TMemoryStream.Write(TBytes, Longint); 
related to 0032179 resolvedJonas Maebe Wrong priority for string for overloaded methods 

Activities

Pascal Riekenberg

2019-05-13 11:28

reporter  

Error.png (5,725 bytes)
Error.png (5,725 bytes)

Ondrej Pokorny

2019-05-13 12:46

reporter   ~0116157

Confirmed: I got a similar exception after r42042 in my own application (not Lazarus).

Do-wan Kim

2019-05-13 17:04

reporter   ~0116170

function read on TBytes declaration is missing 'var' on parameter. That makes problem.

classes_TStream_35576.patch (2,743 bytes)
Index: rtl/objpas/classes/classesh.inc
===================================================================
--- rtl/objpas/classes/classesh.inc	(revision 42056)
+++ rtl/objpas/classes/classesh.inc	(working copy)
@@ -900,8 +900,8 @@
     Procedure WriteExactSizeData(Const Buffer; aSize,aCount : NativeInt);
   public
     function Read(var Buffer; Count: Longint): Longint; virtual;
-    function Read(Buffer: TBytes; Count: Longint): Longint; overload;
-    function Read(Buffer : TBytes; aOffset, Count: Longint): Longint; overload;
+    function Read(var Buffer: TBytes; Count: Longint): Longint; overload;
+    function Read(var Buffer: TBytes; aOffset, Count: Longint): Longint; overload;
 
     function Write(const Buffer: TBytes; Offset, Count: Longint): Longint; overload;
     function Write(const Buffer: TBytes; Count: Longint): Longint; overload;
@@ -910,8 +910,8 @@
     function Seek(Offset: Longint; Origin: Word): Longint; virtual; overload;
     function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; virtual; overload;
 
-    function ReadData(Buffer: Pointer; Count: NativeInt): NativeInt; overload;
-    function ReadData(const Buffer: TBytes; Count: NativeInt): NativeInt; overload;
+    function ReadData(var Buffer: Pointer; Count: NativeInt): NativeInt; overload;
+    function ReadData(var Buffer: TBytes; Count: NativeInt): NativeInt; overload;
     function ReadData(var Buffer: Boolean): NativeInt; overload;
     function ReadData(var Buffer: Boolean; Count: NativeInt): NativeInt; overload;
     function ReadData(var Buffer: AnsiChar): NativeInt; overload;
Index: rtl/objpas/classes/streams.inc
===================================================================
--- rtl/objpas/classes/streams.inc	(revision 42056)
+++ rtl/objpas/classes/streams.inc	(working copy)
@@ -30,12 +30,12 @@
   Result := 0;
 end;
 
-function TStream.Read(Buffer: TBytes; Count: Longint): Longint;
+function TStream.Read(var Buffer: TBytes; Count: Longint): Longint;
 begin
   Result:=Read(Buffer,0,Count);
 end;
 
-function TStream.Read(Buffer: TBytes; aOffset, Count: Longint): Longint;
+function TStream.Read(var Buffer: TBytes; aOffset, Count: Longint): Longint;
 begin
   Result:=Read(Buffer[aOffset],Count);
 end;
@@ -198,12 +198,12 @@
       Result:=Seek(longint(Offset),ord(Origin));
     end;
 
- function TStream.ReadData(Buffer: Pointer; Count: NativeInt): NativeInt;
+ function TStream.ReadData(var Buffer: Pointer; Count: NativeInt): NativeInt;
  begin
    Result:=Read(Buffer^,Count);
  end;
 
- function TStream.ReadData(const Buffer: TBytes; Count: NativeInt): NativeInt;
+ function TStream.ReadData(var Buffer: TBytes; Count: NativeInt): NativeInt;
  begin
    Result:=Read(Buffer,0,Count);
  end;

Ondrej Pokorny

2019-05-13 20:50

reporter   ~0116173

The "function ReadData(Buffer: Pointer; Count: NativeInt): NativeInt;" doesn't need a var. But for the other cases - yes, you are right.

Pascal Riekenberg

2019-05-13 20:52

reporter   ~0116174

Attached patch solves the issue for me. Thanks.
Don't know if it is still Delphi compatible, which was the intention of r42042.

Ondrej Pokorny

2019-05-13 21:56

reporter   ~0116175

Here is a test project:

program Project1;
{$mode objfpc}
uses
  SysUtils, Classes;
var
  B1, B2: TBytes;
  S: TMemoryStream;
  I: Integer;
begin
  B1 := [1, 2, 3, 4, 5];
  S := TMemoryStream.Create;
  S.Write(B1[0], Length(B1));
  S.Position := 0;
  SetLength(B2, Length(B1));
  S.ReadData(B2, Length(B2));
  S.Free;
  if not(Length(B2) = Length(B1)) then
    Halt(999);
  for I := Low(B1) to High(B1) do
    if B1[I] <> B2[I] then
      Halt(I);
  Writeln('OK');
end.

Michael Van Canneyt

2019-05-13 22:17

administrator   ~0116176

Applied partially.

The var is not necessary for the reading... (the pointer is not changed, after all)
Here is the declaration in delphi:
    function Read(Buffer: TBytes; Offset, Count: Longint): Longint; overload; virtual;

The only reason I can see why it would be necessary is so the compiler does not choose the wrong overload.
But I fail to see why the compiler would choose a TBytes call for a record...

Some things remain a mystery :(

Please test and close if OK.

Pascal Riekenberg

2019-05-14 00:43

reporter   ~0116180

r42059:
[FORMS.PP] ExceptionOccurred
  Sender=Edecompressionerror
  Exception=buffer error
  Stack trace:
  $00522DE2 TDECOMPRESSIONSTREAM__READ, line 301 of ./paszlib/src/zstream.pp
  $0051519D DECODE, line 771 of ./fcl-image/src/fpreadpng.pp
  $00514EF8 TFPREADERPNG__DODECOMPRESS, line 787 of ./fcl-image/src/fpreadpng.pp
  $004E8FF3 TLAZREADERPNG__DODECOMPRESS, line 6084 of intfgraphics.pas
  $00515A8B TFPREADERPNG__INTERNALREAD, line 828 of ./fcl-image/src/fpreadpng.pp
  $004E9078 TLAZREADERPNG__INTERNALREAD, line 6101 of intfgraphics.pas
  $004CDBDC TFPCUSTOMIMAGEREADER__IMAGEREAD, line 254 of ./fcl-image/src/fphandler.inc
  $00541231 TCUSTOMICON__READSTREAM, line 897 of ./include/icon.inc
  $005318F7 TRASTERIMAGE__LOADFROMSTREAM, line 441 of ./include/rasterimage.inc
  $00531751 TRASTERIMAGE__LOADFROMSTREAM, line 417 of ./include/rasterimage.inc
  $00540D07 TCUSTOMICON__READDATA, line 796 of ./include/icon.inc
  $00542F35 TICON__LOADFROMRESOURCEHANDLE, line 1435 of ./include/icon.inc
  $00448C57 TAPPLICATION__INITIALIZE, line 463 of ./include/application.inc
  $0040378D main, line 132 of lazarus.pp
TApplication.HandleException: Edecompressionerror
buffer error
  Stack trace:
  $00522DE2 TDECOMPRESSIONSTREAM__READ, line 301 of ./paszlib/src/zstream.pp
  $0051519D DECODE, line 771 of ./fcl-image/src/fpreadpng.pp
  $00514EF8 TFPREADERPNG__DODECOMPRESS, line 787 of ./fcl-image/src/fpreadpng.pp
  $004E8FF3 TLAZREADERPNG__DODECOMPRESS, line 6084 of intfgraphics.pas
  $00515A8B TFPREADERPNG__INTERNALREAD, line 828 of ./fcl-image/src/fpreadpng.pp
  $004E9078 TLAZREADERPNG__INTERNALREAD, line 6101 of intfgraphics.pas
  $004CDBDC TFPCUSTOMIMAGEREADER__IMAGEREAD, line 254 of ./fcl-image/src/fphandler.inc
  $00541231 TCUSTOMICON__READSTREAM, line 897 of ./include/icon.inc
  $005318F7 TRASTERIMAGE__LOADFROMSTREAM, line 441 of ./include/rasterimage.inc
  $00531751 TRASTERIMAGE__LOADFROMSTREAM, line 417 of ./include/rasterimage.inc
  $00540D07 TCUSTOMICON__READDATA, line 796 of ./include/icon.inc
  $00542F35 TICON__LOADFROMRESOURCEHANDLE, line 1435 of ./include/icon.inc
  $00448C57 TAPPLICATION__INITIALIZE, line 463 of ./include/application.inc
  $0040378D main, line 132 of lazarus.pp

Pascal Riekenberg

2019-05-14 00:45

reporter  

Unbenannt.png (8,552 bytes)
Unbenannt.png (8,552 bytes)

Do-wan Kim

2019-05-14 01:38

reporter   ~0116182

Last edited: 2019-05-14 02:12

View 2 revisions

I also got problem with lastest trunk r42059.

function Read(var Buffer; Count: Longint): Longint; virtual; overload; // overload makes problem.

Ondrej Pokorny

2019-05-14 07:01

reporter   ~0116183

The overload keyword makes hardly problems.

The problem is that the other 2 TBuffer overloads miss a "var". (Only the Pointer overload doesn't need it.)

> Here is the declaration in delphi:
> function Read(Buffer: TBytes; Offset, Count: Longint): Longint; overload; virtual;
AFAIK this works in Delphi because arrays do not have copy-on-write:
https://stackoverflow.com/questions/26734992/copy-on-write-for-array-of-records
and therefore the "Buffer: TBytes" gets modified even if it is not var. FPC obviously behaves differently when arrays are used in function arguments and needs a var.

Ondrej Pokorny

2019-05-14 07:06

reporter  

readbuffer-var.patch (2,046 bytes)
Index: rtl/objpas/classes/classesh.inc
===================================================================
--- rtl/objpas/classes/classesh.inc	(revision 42061)
+++ rtl/objpas/classes/classesh.inc	(working copy)
@@ -901,7 +901,7 @@
   public
     function Read(var Buffer; Count: Longint): Longint; virtual; overload;
     function Read(var Buffer: TBytes; Count: Longint): Longint; overload;
-    function Read( Buffer : TBytes; aOffset, Count: Longint): Longint; overload;
+    function Read(var Buffer: TBytes; aOffset, Count: Longint): Longint; overload;
 
     function Write(const Buffer: TBytes; Offset, Count: Longint): Longint; overload;
     function Write(const Buffer: TBytes; Count: Longint): Longint; overload;
@@ -911,7 +911,7 @@
     function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; virtual; overload;
 
     function ReadData(Buffer: Pointer; Count: NativeInt): NativeInt; overload;
-    function ReadData(Buffer: TBytes; Count: NativeInt): NativeInt; overload;
+    function ReadData(var Buffer: TBytes; Count: NativeInt): NativeInt; overload;
     function ReadData(var Buffer: Boolean): NativeInt; overload;
     function ReadData(var Buffer: Boolean; Count: NativeInt): NativeInt; overload;
     function ReadData(var Buffer: AnsiChar): NativeInt; overload;
Index: rtl/objpas/classes/streams.inc
===================================================================
--- rtl/objpas/classes/streams.inc	(revision 42061)
+++ rtl/objpas/classes/streams.inc	(working copy)
@@ -35,7 +35,7 @@
   Result:=Read(Buffer,0,Count);
 end;
 
-function TStream.Read(Buffer: TBytes; aOffset, Count: Longint): Longint;
+function TStream.Read(var Buffer: TBytes; aOffset, Count: Longint): Longint;
 begin
   Result:=Read(Buffer[aOffset],Count);
 end;
@@ -203,7 +203,7 @@
    Result:=Read(Buffer^,Count);
  end;
 
- function TStream.ReadData({var} Buffer: TBytes; Count: NativeInt): NativeInt;
+ function TStream.ReadData(var Buffer: TBytes; Count: NativeInt): NativeInt;
  begin
    Result:=Read(Buffer,0,Count);
  end;
readbuffer-var.patch (2,046 bytes)

Michael Van Canneyt

2019-05-14 07:46

administrator   ~0116185

Free Pascal also does not have copy on write for TBytes. It is explicitly documented.

https://www.freepascal.org/docs-html/current/ref/refsu14.html#x38-490003.3.1

Check the example (I verified it to be sure)

So there must be another reason for the var to be necessary.

As I said, I did tests and the tests work fine without the var.

So the read itself is OK, the problem is: why does the compiler sometimes choose the wrong overload.

What's more:
Why is the behaviour of non-TBytes reading (such as in the icon or other streams) affected by adding a TBytes overload ?

Ondrej Pokorny

2019-05-14 07:47

reporter   ~0116186

@Do-wan Kim: you are right, the overload makes trouble in objfpc mode 0035580:0116184 ... This is horribly confusing. Sorry for the spam.

I still don't understand why only the one function needs a var and the others don't - a var would be definitively cleaner there.

Ondrej Pokorny

2019-05-14 08:01

reporter   ~0116188

> As I said, I did tests and the tests work fine without the var.
Yes, you are right. It works without the var. But only for the one overload. You still need a var for:
function TStream.Read(var Buffer: TBytes; Count: Longint): Longint;
Why? Strangely, Delphi has it there as well. If there is no COW for TBytes, why do we need a var there? The pointer is the same.
If we need a var here but not in the other similar cases, having a var for TBytes everywhere would be cleaner even if it is not needed, IMO. This looks to me that it depends on some compiler internal undocumented behavior we can only hope won't change.

> Why is the behaviour of non-TBytes reading (such as in the icon or other streams) affected by adding a TBytes overload ?

Non-TBytes (records etc.) are not affected. Affected are the dereferenced Byte-arrays within the records, depending on current compiler mode.

Michael Van Canneyt

2019-05-14 08:19

administrator   ~0116189

Last edited: 2019-05-14 08:19

View 2 revisions

@Ondrej,

yes, see https://bugs.freepascal.org/view.php?id=35576#c116176

That is why I applied the var patch for the
    function Read(var Buffer: TBytes; Count: Longint): Longint; overload;
for the other (with offset) the patch is not needed, since there are no other read calls with that signature (3 args).

Remains to see how to solve the problem with the compiler overload choosing behaviour...

Ondrej Pokorny

2019-05-14 09:34

reporter   ~0116195

Aaah, I see now - the problem is not about var/const but about overload resolving - even here. The problem was that without the var the TBytes-overload was called even for array[0..0] of Byte:

program Project1;
{$mode objfpc}
uses
  SysUtils, Classes;
var
  B: TBytes;
  C: array[0..4] of Byte;
  S: TMemoryStream;
  I: Integer;
begin
  B := [1, 2, 3, 4, 5];
  S := TMemoryStream.Create;
  S.Write(B[0], Length(B));
  S.Position := 0;
  S.Read(C, Length(C)); // << TStream.Read(Buffer: TBytes; Count: Longint) was called in objfpc mode (mode Delphi worked fine) before r42057
  S.Free;
  if not(Length(C) = Length(B)) then
    Halt(999);
  for I := Low(B) to High(B) do
    if B[I] <> C[I] then
      Halt(I);
  Writeln('OK');
end.

The var made the compiler not to pick up the TBytes-overload for "array[0..4] of Byte". Funny, though, in Delphi mode the compiler picked up the const-overload. So this was an overload resolving problem.

Awkward

2019-05-16 23:19

reporter   ~0116227

Tried patch from Ondrej Pokorny. tried just latest FPC commits (42087), Lazarus crashing with messagebox about "buffer error" when compiled with FPC trunk

Serge Anvarov

2019-05-18 05:02

reporter   ~0116241

r42090 already include a patch, but lazarus still won't start (same error)

Oleg

2019-05-18 12:28

reporter   ~0116244

Lazarus starts without problems after removing the function TStream.Read(var Buffer: TBytes; Count: Longint): Longint; and rebuild FPC(r42090) & Lazarus(r61236)

Serge Anvarov

2019-05-18 20:43

reporter   ~0116251

It didn't help me. FPC r42092, Lazarus r61239. Remove TStream.Read(var Buffer: TBytes; Count: Longint): Longint; rebuilt both. Next remove also TStream.Read(Buffer: TBytes; Count: Longint): Longint; rebuilt both.

Oleg

2019-05-20 04:53

reporter   ~0116275

Sorry, two methods have been removed:
function TStream.Read(var Buffer: TBytes; Count: Longint): Longint;
function TStream.Write(const Buffer: TBytes; Count: Longint): Longint;

Now tested FPC(r42099), Lazarus(r61245) Win32 and Win64 - Lazarus starts without problems.

Michael Van Canneyt

2019-05-20 08:34

administrator   ~0116276

Of course removing these will fix the problem. You are undoing what caused the problem.

But adding them is needed for Delphi compatibility (see 0035330).
There is a compiler error that makes the compiler choose the wrong overload.

Pascal Riekenberg

2019-05-20 12:49

reporter   ~0116279

>There is a compiler error that makes the compiler choose the wrong overload.
Is someone working on this?

Michael Van Canneyt

2019-05-20 13:20

administrator   ~0116280

I have asked already twice, no reaction. Feel free to ask on the fpc-devel mailing list.

stocki

2019-05-20 19:28

reporter   ~0116287

Last edited: 2019-05-20 19:36

View 3 revisions

Current trunk does not start.

-Checked out revision 42110.
-Checked out revision 61248.
-Win64

Jonas Maebe

2019-05-22 22:16

manager   ~0116349

There is indeed code that is specific to FPC modes that allows for type conversions of regular arrays to dynamic arrays (so you can assign regular arrays to dynamic arrays, and pass regular arrays to dynamic array parameters), while Delphi does not support this. It was added in March 2005.

The only solution I see to fix this bug, is to completely remove support for this type conversion. It is not possible to make the "array to formal const" type conversion preferred over the "array to dynamic array" type conversion, because formal const has the lowest priority of all (it's a fallback since anything can be passed to it). Only disabling it for parameters would be a very ugly hack (either a type conversion is supported, or it's not).

Pascal Riekenberg

2019-05-23 09:11

reporter   ~0116363

What about a new local directive to prevent type conversion for the next parameter. This way the code where the wrong overload is picked can be adjusted.

Jonas Maebe

2019-05-23 19:18

manager   ~0116375

That's an even worse hack.

However, I just noticed that in spite of the fact that this rule has been in the compiler since a very long time, FPC 3.0.4 still calls the other overload in my test program. So maybe something else also changed and it can still be changed in a way that remains compatible with everything.

Jonas Maebe

2019-05-23 20:39

manager   ~0116377

The reason it worked with FPC 3.0.4 is that formal constants had a much higher conversion preference. This was changed to fix 0032179

Marco van de Voort

2019-05-25 12:52

manager   ~0116408

But that was also Delphi compatibility related it seems? So why doesn't that same case bite then in Delphi?

Jonas Maebe

2019-05-25 14:32

manager   ~0116410

I have disabled the "regular array" to "dynamic array" type conversion in all syntax modes by default. It can be re-enabled with {$modeswitch arraytodynarray}. I'll document it on the wiki as well.

Issue History

Date Modified Username Field Change
2019-05-13 11:28 Pascal Riekenberg New Issue
2019-05-13 11:28 Pascal Riekenberg File Added: Error.png
2019-05-13 12:46 Ondrej Pokorny Note Added: 0116157
2019-05-13 17:04 Do-wan Kim File Added: classes_TStream_35576.patch
2019-05-13 17:04 Do-wan Kim Note Added: 0116170
2019-05-13 20:50 Ondrej Pokorny Note Added: 0116173
2019-05-13 20:52 Pascal Riekenberg Note Added: 0116174
2019-05-13 21:41 Jonas Maebe Assigned To => Michael Van Canneyt
2019-05-13 21:41 Jonas Maebe Status new => assigned
2019-05-13 21:56 Ondrej Pokorny Note Added: 0116175
2019-05-13 22:17 Michael Van Canneyt Status assigned => resolved
2019-05-13 22:17 Michael Van Canneyt Resolution open => fixed
2019-05-13 22:17 Michael Van Canneyt Fixed in Revision => 42057.
2019-05-13 22:17 Michael Van Canneyt FPCTarget => -
2019-05-13 22:17 Michael Van Canneyt Note Added: 0116176
2019-05-14 00:43 Pascal Riekenberg Status resolved => feedback
2019-05-14 00:43 Pascal Riekenberg Resolution fixed => reopened
2019-05-14 00:43 Pascal Riekenberg Note Added: 0116180
2019-05-14 00:45 Pascal Riekenberg File Added: Unbenannt.png
2019-05-14 01:38 Do-wan Kim Note Added: 0116182
2019-05-14 02:12 Do-wan Kim Note Edited: 0116182 View Revisions
2019-05-14 07:01 Ondrej Pokorny Note Added: 0116183
2019-05-14 07:06 Ondrej Pokorny File Added: readbuffer-var.patch
2019-05-14 07:46 Michael Van Canneyt Note Added: 0116185
2019-05-14 07:47 Ondrej Pokorny Note Added: 0116186
2019-05-14 08:01 Ondrej Pokorny Note Added: 0116188
2019-05-14 08:14 Michael Van Canneyt Relationship added related to 0035580
2019-05-14 08:19 Michael Van Canneyt Note Added: 0116189
2019-05-14 08:19 Michael Van Canneyt Note Edited: 0116189 View Revisions
2019-05-14 09:34 Ondrej Pokorny Note Added: 0116195
2019-05-16 23:19 Awkward Note Added: 0116227
2019-05-18 05:02 Serge Anvarov Note Added: 0116241
2019-05-18 12:28 Oleg Note Added: 0116244
2019-05-18 20:43 Serge Anvarov Note Added: 0116251
2019-05-20 04:53 Oleg Note Added: 0116275
2019-05-20 08:34 Michael Van Canneyt Note Added: 0116276
2019-05-20 12:49 Pascal Riekenberg Note Added: 0116279
2019-05-20 12:49 Pascal Riekenberg Status feedback => assigned
2019-05-20 13:20 Michael Van Canneyt Note Added: 0116280
2019-05-20 19:28 stocki Note Added: 0116287
2019-05-20 19:34 stocki Note Edited: 0116287 View Revisions
2019-05-20 19:36 stocki Note Edited: 0116287 View Revisions
2019-05-22 22:16 Jonas Maebe Note Added: 0116349
2019-05-23 09:11 Pascal Riekenberg Note Added: 0116363
2019-05-23 19:18 Jonas Maebe Note Added: 0116375
2019-05-23 20:39 Jonas Maebe Note Added: 0116377
2019-05-23 20:40 Jonas Maebe Relationship added related to 0032179
2019-05-25 12:34 Michael Van Canneyt Note View State: 0116377: private
2019-05-25 12:34 Michael Van Canneyt Note View State: 0116377: public
2019-05-25 12:52 Marco van de Voort Note Added: 0116408
2019-05-25 14:32 Jonas Maebe Status assigned => resolved
2019-05-25 14:32 Jonas Maebe Resolution reopened => fixed
2019-05-25 14:32 Jonas Maebe Note Added: 0116410
2019-05-25 14:33 Jonas Maebe Fixed in Revision 42057. => 42057, 42118
2019-05-27 09:20 Pascal Riekenberg Status resolved => closed