Recent

Author Topic: Doomed name  (Read 5143 times)

LemonParty

  • Jr. Member
  • **
  • Posts: 65
Doomed name
« on: April 14, 2024, 06:22:10 pm »
Hi.
I have a unit with function that described like this:
Code: Pascal  [Select][+][-]
  1. function Pos(constref Str: AnsiChar; C: AnsiChar; Range: SizeUInt): SizeUInt;
When I call this function I getting 0 no matter what. Than I changed the name of function to "PosR" and it started work as needed. When I attempted to reproduce this behavior in small project I sometimes get this error message:
Quote
Error: Undefined symbol: UNIT1_::=::\_POS$ANSISTRING$CHAR$INT64::=::\QWORD
, in other time it compiles and execute as expected.
FPC 3.2.2.
Is this bug or what?

Eugene Loza

  • Hero Member
  • *****
  • Posts: 690
    • My games in Pascal
Re: Doomed name
« Reply #1 on: April 14, 2024, 07:38:07 pm »
Note that Pos is an internal Pascal function https://www.freepascal.org/docs-html/rtl/system/pos.html and usually it's a very bad idea trying to name something like that.

Hypothetically it should still detect the proper namespace and apply your custom function as an overload. But there are plenty of Pos overloads already and looks like eventually it gets confused as to which exactly implementation to call.

Shouldn't crash though. So if you can get a reliable reproduction this may be a candidate for a bugreport.
My FOSS games in FreePascal&CastleGameEngine: https://decoherence.itch.io/ (Sources: https://gitlab.com/EugeneLoza)

domasz

  • Sr. Member
  • ****
  • Posts: 443
Re: Doomed name
« Reply #2 on: April 14, 2024, 07:49:59 pm »
Try to call your function like this:

Code: Pascal  [Select][+][-]
  1. YOUR_UNIT_NAME.Pos(...)

Ten_Mile_Hike

  • Jr. Member
  • **
  • Posts: 54
Re: Doomed name
« Reply #3 on: April 14, 2024, 08:13:46 pm »
It is best to "PRETEND" that all built in function and procedure names are "Reserved words"
for your own sanity and the sanity of the guy who inherits your code.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9983
  • Debugger - SynEdit - and more
    • wiki
Re: Doomed name
« Reply #4 on: April 14, 2024, 11:23:21 pm »
error message:
Quote
Error: Undefined symbol: UNIT1_::=::\_POS$ANSISTRING$CHAR$INT64::=::\QWORD
, in other time it compiles and execute as expected.

Maybe, maybe not.

Apart from what others said: If you use names of functions that exist in other units, then you must make sure the units are used in a way that yours will be found....
But that has nothing to do with the above case.

I wonder, if you have units in different folders? If you search, do you have more than one unit1.ppu or more than one unit1.o? Or do those 2 have different time stamps?

Did you in any way touch any settings on the "path" tab of the project options? (or otherwise manipulate pathes used by fpc?)

LemonParty

  • Jr. Member
  • **
  • Posts: 65
Re: Doomed name
« Reply #5 on: April 15, 2024, 12:16:12 pm »
Can't reproduce this situation on a small unit. Changed name of function to PosR for now. Thank you for suggestions.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9983
  • Debugger - SynEdit - and more
    • wiki
Re: Doomed name
« Reply #6 on: April 15, 2024, 01:05:54 pm »
Can't reproduce this situation on a small unit. Changed name of function to PosR for now. Thank you for suggestions.
If this only happens with a more complex project, I would suggest to check (in your project, and any package you wrote yourself or modified) to check if you changed any PATH settings -Fi -Fu -FU -Fe ......

I would also suggest, across all folders (project and packages) to search for duplicate files with the ending .ppu or .o (e.g. if there is a unit1.ppu in 2 different folders that are both in any way accessible for the compiler while compiling the project)

Also ensure to make a very clean build: find and delete all *.ppu and *.o files of your project (and packages)
(except closed source 3rd party packages that only provided ppu/o files, but no sources)




Further more, search if you have any procedures that you explicitly named.
procedure foo; external name 'abc';
procedure foo; external 'abc';
procedure foo; public name 'abc';
or similar stuff...
« Last Edit: April 15, 2024, 01:07:36 pm by Martin_fr »

LemonParty

  • Jr. Member
  • **
  • Posts: 65
Re: Doomed name
« Reply #7 on: April 17, 2024, 05:57:11 pm »
Yes. I reproduced this thing.
Unit1.pas
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode ObjFPC}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.  Classes, SysUtils;
  9.  
  10. function Pos(constref str: AnsiChar; C: AnsiChar; Range: SizeUInt): SizeUInt;
  11.  
  12. function Pos(str: AnsiString; C: AnsiChar; Offset: SizeInt): SizeUInt;inline;
  13.  
  14. implementation
  15.  
  16. function Pos(constref Str: AnsiChar; C: AnsiChar; Range: SizeUInt): SizeUInt;
  17. var
  18.         pCh: PChar;
  19. begin
  20.         Result:= 0;
  21.         pCh:= @Str;
  22.         if pCh <> nil then
  23.                 for Range:= 1 to Range do begin
  24.                         if pCh^ = C then
  25.                                 Exit(Range);
  26.                         inc(pCh);
  27.                 end;
  28. end;
  29.  
  30. { as in System library }
  31. function Pos(str: AnsiString; C: AnsiChar; Offset: SizeInt): SizeUInt;inline;
  32. begin
  33.         if (Offset > 0) and (Offset <= Length(str))
  34.                 then Result:= Pos(str[Offset], C, Length(str)-Offset+1)
  35.                 else Result:= 0;
  36. end;
  37.  
  38. end.
  39.  
Than use it like this:
Code: Pascal  [Select][+][-]
  1. unit1.Pos(S[1], ' ', Length(S));
Where S is some string. Always return 0, also can't "Step Into".

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9983
  • Debugger - SynEdit - and more
    • wiki
Re: Doomed name
« Reply #8 on: April 17, 2024, 06:23:11 pm »
Looks like it calls the inlined "pos". Just remove the inline for debugging.


If you want the "char" version to be called
Code: Pascal  [Select][+][-]
  1.   unit2.Pos(S[1], ' ', SizeUInt(Length(S)));

"Length" returns a signed value. And so fpc has to choose to either call the "pos" with the mismatch in signed-ness, or the pos with the string<>char.

I don't know the internal rules, but apparently it calls the one with the matching signed-ness, and the char<>string mismatch.

LemonParty

  • Jr. Member
  • **
  • Posts: 65
Re: Doomed name
« Reply #9 on: April 17, 2024, 06:59:01 pm »
I remove "inline".
Code: Pascal  [Select][+][-]
  1. function Pos(str: AnsiString; C: AnsiChar; Offset: SizeInt): SizeUInt;
  2.  
called. This is kind of weird because I call it with S[1] which is not a string.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9983
  • Debugger - SynEdit - and more
    • wiki
Re: Doomed name
« Reply #10 on: April 17, 2024, 07:31:38 pm »
Calling the other "Pos" would be "weird" too. Because the result of "length" is "SizeInt" and not "SizeUInt".

And casting a SizeInt to a SizeUint can result in out-of-range. 

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9983
  • Debugger - SynEdit - and more
    • wiki
Re: Doomed name
« Reply #11 on: April 17, 2024, 07:48:23 pm »
Btw, while testing (using fpc 3.2.3), I did notice that when the "char" variant is called, the compiler inserts a call to fpc_ansistr_unique before it makes the call.

That means, if the string has more than one reference, then a copy of the string will be made.
This doesn't affect the result you get, but it will likely slow down your code.


LemonParty

  • Jr. Member
  • **
  • Posts: 65
Re: Doomed name
« Reply #12 on: April 17, 2024, 08:25:20 pm »
I changed Range: SizeUInt to Range: SizeInt. Now it picking the right function.
Quote
This doesn't affect the result you get, but it will likely slow down your code.
How I can avoid this?

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9983
  • Debugger - SynEdit - and more
    • wiki
Re: Doomed name
« Reply #13 on: April 17, 2024, 09:09:52 pm »
I changed Range: SizeUInt to Range: SizeInt. Now it picking the right function.
Quote
This doesn't affect the result you get, but it will likely slow down your code.
How I can avoid this?

I don't know why fpc puts it there, or if all versions of fpc do.

For fpc 3.2.3 (at least at -O1) using an untyped parameter "procedure Pos(const str; c: ansichar; o: sizeint);" does not trigger it. But, without knowing why it is triggered in the first case, there is no telling if that is for all settings and/or versions.

Also, an untyped param, may lead to new issues with the overload detection...

Maybe someone from the fpc team will know.

 

TinyPortal © 2005-2018