Recent

Author Topic: Could you please help me understand this compiler error message?  (Read 730 times)

EganSolo

  • Full Member
  • ***
  • Posts: 212
I downloaded the codebot package from https://github.com/sysrpl/Cross.Codebot.
loaded it and hit compile and got the following compilation error:
codebot.interop.windows.gdiplus.pas(11906,45) Error: Can't determine which overloaded function to call.

The suspect code line, located in the unit gdiplus.pas at line 11,906 (as the error message states) is this:
Code: Pascal  [Select][+][-]
  1.   B := TGdiBitmap.Create(Size * 2, Size * 2); //size is declared as an integer

I thought the constructor is overloaded and two or more signatures are confusing the compiler. But when I checked these signatures, nothing seemed amiss. What am I missing?
Here are these signatures. I've numbered them for ease of discussion
Code: Pascal  [Select][+][-]
  1.     {01} constructor Create(Bitmap: GpBitmap); overload;
  2.     {02} constructor Create(Filename: WideString; UseEmbeddedColorManagement: Boolean = False); overload;
  3.     {03} constructor Create(Stream: IStream; UseEmbeddedColorManagement: Boolean = False); overload;
  4.     {04} constructor Create(Width, Height, Stride: Integer; Format: TPixelFormat; scan0: PByte); overload;
  5.     {05} constructor Create(Width, Height: Integer; Format: TPixelFormat = PixelFormat32bppArgb); overload;
  6.     {06} constructor Create(Width, Height: Integer; Target: IGdiGraphics); overload;
  7.     {07} constructor Create(surface: IDirectDrawSurface7); overload;
  8.     {08} constructor Create(var BitmapInfo: TBitmapInfo; BitmapData: Pointer); overload;
  9.     {09} constructor Create(Bmp: HBitmap; Pal: HPALETTE); overload;
  10.     {10} constructor Create(Icon: HICON); overload;
  11.     {11} constructor Create(hInstance: HMODULE; BitmapName: WideString); overload;
  12.     //The next set of constructors is taken from the superclass TGdiImge:
  13.     {12} constructor Create; overload;
  14.     {13} constructor Create(Image: GpImage; Status: TStatus); overload;
  15.     {14} constructor Create(Filename: WideString; UseEmbeddedColorManagement: Boolean = False); overload;
  16.     {15} constructor Create(Stream: IStream; UseEmbeddedColorManagement: Boolean = False); overload;
  17.   //Finally, TGDIobject has one constructor.
  18.     {16} constructor Create;
  19.   //TGDIObject derives from TInterfacedObject which has no constructors, and TInterfacedObject derives from TObject
  20.  

Since size is an integer, the signature at 11,906 is (integer, integer), which matches the signature of constructor number 5 in the list above, but I'm not able to tell which other signature is clashing with this one. I've already logged an issue on the github of the library, but this is bugging me.

Environment: Lazarus v2.0.12r64642 on windows.

Jonas Maebe

  • Hero Member
  • *****
  • Posts: 865
Re: Could you please help me understand this compiler error message?
« Reply #1 on: March 29, 2021, 11:24:44 am »
If you compile with hints enabled, the compiler should print a list of all possible methods it found.

EganSolo

  • Full Member
  • ***
  • Posts: 212
Re: Could you please help me understand this compiler error message?
« Reply #2 on: March 29, 2021, 11:41:05 am »
Jonas, thanks. I _did_ compile with hints enabled and didn't look: The hint is pointing at constructor number 9 declared as
Code: Pascal  [Select][+][-]
  1.   constructor Create(Bmp: HBitmap; Pal: HPALETTE); overload;
  2.  

HBitmap and HPALETTE both resolve (after a long chain of definition) to QWord (I'm on Windows 64 bits) and Integer resolves to longint (in objpas). According to the language guide,
Longint = -2147483648 .. 2147483647 and it's four bytes long, while QWord = 0 .. 18446744073709551615  and is 8 bytes long. So, if the code is making a call with 2 * Size where size is integer shouldn't the compiler resolve to integer? Why is it being confused between integer and Qword?

rvk

  • Hero Member
  • *****
  • Posts: 4472
Re: Could you please help me understand this compiler error message?
« Reply #3 on: March 29, 2021, 12:17:57 pm »
Why do you think it should resolve to integer.
You have Size * 2 where Size is an integer.
That doesn't mean the result also fits into an integer.
If Size is bigger than MaxInt / 2 it won't fit.
And the compiler doesn't know what the value will be during runtime.

If you would write Integer(Size * 2) it might work, but that's not really a good solution.

You could add PixelFormat32bppArgb as 3rd parameter and it will resolve correctly.
But I think the compiler is correct here that is really doesn't know if it should use Integer or QWord (because Size could be bigger).

lucamar

  • Hero Member
  • *****
  • Posts: 3877
Re: Could you please help me understand this compiler error message?
« Reply #4 on: March 29, 2021, 04:29:13 pm »
But I think the compiler is correct here that is really doesn't know if it should use Integer or QWord (because Size could be bigger).

That could as well be considered a bug: if anything, it should resolve to Int64, not to QWord, to allow for negative values. What is probably happening is that it is resolving to Int64 but when searching for the correct overload it can't decide whether to typecast down to Integer or to QWord, since both might potentially mean a lost of precission. Hence the message: It can't determine which overload wil produce a more precise result.

To solve the dilemma you should use an intermediate variable of the proper type to keep the result of the operation and pass it as-is to the constructor, so:

Code: Pascal  [Select][+][-]
  1.   W := Size*2; {var Size, W: Integer}
  2.   B := TGdiBitmap.Create(W, W);
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

jamie

  • Hero Member
  • *****
  • Posts: 4446
Re: Could you please help me understand this compiler error message?
« Reply #5 on: March 29, 2021, 10:53:51 pm »
That's an old problem...

 Doing math within the parameter clauses changes the type on the left.. it does not keep with the type that it started with...

 I don't know what SIZE is but I bet it isn't a integer to start with ? That being the case now you have two types , the first one you started with "Size" and now a Integer you ended with.

 if type casting fixes the issue then that is what the issue is..

 This works fine in Delphi btw.. Type stays the same after math and thus knows exactly what function to call if one matches of course.

 Hope you have better luck than I did trying to convince them otherwise.

The only true wisdom is knowing you know nothing

lucamar

  • Hero Member
  • *****
  • Posts: 3877
Re: Could you please help me understand this compiler error message?
« Reply #6 on: March 30, 2021, 12:48:46 am »
I don't know what SIZE is but I bet it isn't a integer to start with ?

Acording to the comment in the  OP's code, it is an Integer.

Quote from: jamie
Doing math within the parameter clauses changes the type on the left.. it does not keep with the type that it started with...

That's is quite logical, otherwise it would be unable to make the calculation. The problem, for Pascal, is that being strong-typed also means that the compiler has to be more careful with type coercion, which makes it look for an overload that could conceivably hold the result if it exceeds the initial type. But here it only finds two, neither of which is really adequate, so it doesn't knows what to do.

I bet that a explicit typecast would also work, as in:
Code: Pascal  [Select][+][-]
  1.   B := TGdiBitmap.Create(Integer(Size * 2), Integer(Size * 2)); //size is declared as an integer
since it resolves the ambiguity.
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

jamie

  • Hero Member
  • *****
  • Posts: 4446
Re: Could you please help me understand this compiler error message?
« Reply #7 on: March 30, 2021, 02:46:00 am »
Let me give you something to chew on..

Code: Pascal  [Select][+][-]
  1. Var
  2.  W:Word;
  3.  
  4. Begin
  5.  W := $00FF;
  6.  Caption := Hi(W+1).Tostring;
  7. End;
  8.  

That should result to a 1 being displayed.

if memory serves, you'll get 0

Why? because the compiler magically changes it to a integer and a HI of the integer is 0 .

if I type cast that within it will then correctly call the correct function, otherwise it calls the HI function for a Integer instead.

last time I checked there are no warnings or complaints about it but if you overload your own functions in code and you start doing things like this within the parameters it generates messages like is being seen here..

This all works perfectly in Delphi..

The over loading is confused with FPC

There is no reason why the compiler can not honor the type on the left when doing such things within a parameter opening.
its just simple logic, you start with a WORD you end with a WORD type.. and if it happens to roll over so be it, maybe that was the intent of the whole exercise ?

« Last Edit: March 30, 2021, 02:49:46 am by jamie »
The only true wisdom is knowing you know nothing

lucamar

  • Hero Member
  • *****
  • Posts: 3877
Re: Could you please help me understand this compiler error message?
« Reply #8 on: March 30, 2021, 06:31:13 am »
There is no reason why the compiler can not honor the type on the left when doing such things within a parameter opening.
its just simple logic, you start with a WORD you end with a WORD type.. and if it happens to roll over so be it, maybe that was the intent of the whole exercise ?

Look at it the other way: When you do SomeWord + 1 you might be expecting the compiler to do whatever it takes to increment some value by one, but that might overshot Hi(Word), so the compiler helpfully decides to cast to Int64. There is nothing there telling it to not do it, that you just want a Word: it's just a byte being added to a word without a explicit final type, so to avoid an overflow it promotes the whole expression to Int64/QWord. That's as documented (IIRC).

If you don't want that behaviour then you must be explicit in what you want:
Code: Pascal  [Select][+][-]
  1. uses
  2.   SysUtils;
  3.  
  4. var
  5.  W:Word;
  6.  
  7. begin
  8.  W := $00FF;
  9.  W := W+1;
  10.  WriteLn(Hi(W).Tostring);
  11.  
  12.  W := $00FF;
  13.  Inc(W);
  14.  WriteLn(Hi(W).Tostring);
  15. end.

Now whether that's different in Delphi and, if so, whether the difference matters enough I shall leave to clearer minds than mine :)

Note that I (very intentionally) don't say whether this is the proper way or not, just that this is how FPC behaves and one has to take it into account.
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

 

TinyPortal © 2005-2018