Recent

Author Topic: Can't determine which overloaded function to call  (Read 544 times)

LemonParty

  • Sr. Member
  • ****
  • Posts: 393
Can't determine which overloaded function to call
« on: February 25, 2025, 08:39:47 pm »
Hi.
I have this code:
Code: Pascal  [Select][+][-]
  1. {$MODE objfpc}{$H+}
  2.  
  3. function F1(constref A: Byte; B: Byte): SizeUInt;
  4. begin
  5.        
  6. end;
  7.  
  8. function F1(constref A: ShortInt; Sh: ShortInt): SizeUInt;
  9. begin
  10.        
  11. end;
  12.  
  13. var
  14.   B: Byte;
  15.   Sh: ShortInt;
  16. begin
  17.   Writeln(
  18.     F1(B, 24),
  19.     F1(Sh, 24)
  20.   );
  21. end.
In FPC 3.2.2 I getting error "Can't determine which overloaded function to call". Is trunk have the same issue?
Lazarus v. 4.99. FPC v. 3.3.1. Windows 11

Khrys

  • Sr. Member
  • ****
  • Posts: 390
Re: Can't determine which overloaded function to call
« Reply #1 on: February 26, 2025, 07:19:52 am »
This ocurrs because the size/type of plain integer literals can't be determined without making some guesses; here's what FPC does:

Quote
That means constants in the range -128..127 are mapped to shortint, constants in range 128..255 are mapped to byte, etc. Constants in the range 2147483647..high(cardinal) are parsed as cardinals, and all decimal constants which do not fit either of the above ranges are parsed as 64-bit integer constants.

So in your case, the compiler assumes that  24  is a  ShortInt  in both calls. But  F1(Byte; ShortInt)  doesn't exist, and because there are exactly two possibilities that are equally valid (Byte & Byte  or  ShortInt & ShortInt), the compiler can't make a guess. Usually it settles with the candidate where the most parameters match, but a 50:50 split is undecidable. Take a look at this little experiment and note how (again) it's the equally-split case that fails:

Code: Pascal  [Select][+][-]
  1. function F(A, B, C, D: Byte): SizeInt; inline;
  2. begin
  3.   Result := 2;
  4. end;
  5.  
  6. function F(A, B, C, D: ShortInt): SizeInt; inline;
  7. begin
  8.   Result := 1;
  9. end;
  10.  
  11. procedure Test();
  12. begin                                          // xor eax, eax
  13.   PSizeInt(Nil)^ := F(100, 100, 100, 100);   // mov [eax], 1  -  ShortInt
  14.   PSizeInt(Nil)^ := F(200, 100, 100, 100);   // mov [eax], 1  -  ShortInt (with range check error on 200)
  15.   PSizeInt(Nil)^ := F(200, 200, 100, 100);   // Error: Can't determine which overloaded function to call
  16.   PSizeInt(Nil)^ := F(200, 200, 200, 100);   // mov [eax], 2  -  Byte
  17.   PSizeInt(Nil)^ := F(200, 200, 200, 200);   // mov [eax], 2  -  Byte
  18. end;



You could just explicitly specify the type of  24  using a cast, e.g.  F1(B, Byte(24))  -  after all, the compiler can't read your mind, so it's better to be explicit in cases like these.

LemonParty

  • Sr. Member
  • ****
  • Posts: 393
Re: Can't determine which overloaded function to call
« Reply #2 on: February 26, 2025, 05:21:45 pm »
Thank you. That's explain something. I thought the compiler should pick the function based on first argument.
Lazarus v. 4.99. FPC v. 3.3.1. Windows 11

PascalDragon

  • Hero Member
  • *****
  • Posts: 6311
  • Compiler Developer
Re: Can't determine which overloaded function to call
« Reply #3 on: March 01, 2025, 09:23:25 pm »
With literal constant values in a suitable range it would at least in theory be possible that the compiler can pick a suitable overload due to the one variable that would fix it. So if you want you can report a bug so that this might be improved in the future. 🤔

 

TinyPortal © 2005-2018