[fpc-devel] Overloading problem in generic class.
Bart
bartjunk64 at gmail.com
Sun Sep 18 11:37:23 CEST 2022
Hi,
The following program will compile for Windows 32 and 64 bit.
It fails to compile for Linix 64 bit (and if I understand correctly,
also for MacOS 64 bit).
=== begin code ===
program test;
{$mode objfpc}
{$H+}
{$ifdef FPC_HAS_TYPE_EXTENDED}
function SameValue(const A, B: Extended): Boolean;inline; overload;
begin
writeln('SameValue Extended');
Result := A=B;
end;
{$endif}
{$ifdef FPC_HAS_TYPE_DOUBLE}
function SameValue(const A, B: Double): Boolean;inline; overload;
begin
writeln('SameValue Double');
Result := A=B;
end;
{$endif}
function SameValue(const A, B: Single): Boolean;inline; overload;
begin
writeln('SameValue Single');
Result := A=B;
end;
type
generic TBase<T> = class
private
const _Def = 1;
public
FValue: T;
function IsStored: Boolean;
end;
function TBase.IsStored: Boolean;
begin
Result := SameValue(FValue, T(_Def)); // << this is line 40
end;
type
TDouble = specialize TBase<Double>;
var
D: TDouble;
const
ADef = 1.0;
begin
{$ifdef WINDOWS}
write('Windows ');
{$endif}
{$ifdef darwin}
write('MacOS ');
{$endif}
{$ifdef linux}
write('Linux ');
{$endif}
{$ifdef CPU32}
writeln('32-bit');
{$ENDIF}
{$ifdef CPU64}
writeln('64-bit');
{$ENDIF}
{$ifdef FPC_HAS_TYPE_EXTENDED}
writeln('FPC_HAS_TYPE_EXTENDED');
{$ELSE}
writeln('NOT FPC_HAS_TYPE_EXTENDED');
{$endif}
{$ifdef FPC_HAS_TYPE_DOUBLE}
writeln('FPC_HAS_TYPE_DOUBLE');
{$ELSE}
writeln('NOT FPC_HAS_TYPE_DOUBLE');
{$endif}
write('Literal 1.0 : ');
SameValue(1.0,ADef);
write('Literal 4E38 : '); //cannot be a single
SameValue(4E38,ADef);
{$ifdef FPC_HAS_TYPE_EXTENDED}
write('Literal 2E308: '); //cannot be a Double
SameValue(2E308,ADef);
{$endif}
write('TDouble : ');
D := TDouble.Create;
D.FValue := 1.0;
D.IsStored;
D.Free;
end.
=== end code ===
Linux 64-bit
Compile Project, Target: test: Exit code 1, Errors: 1, Hints: 3
test.lpr(40,13) Error: Can't determine which overloaded function to call
test.lpr(22,10) Hint: Found declaration: SameValue(const Single;const
Single):Boolean;
test.lpr(15,10) Hint: Found declaration: SameValue(const Double;const
Double):Boolean;
test.lpr(7,10) Hint: Found declaration: SameValue(const Extended;const
Extended):Boolean;
If I remove the typecast then it compiles OK on all platforms.
(fpc 3.2.2 of fpc main seem to do the same)
I simply do not understand where the difference between
Windows/Non-Windows comes from.
Some background:
We had a crash in the Lazarus IDE when setting MaxValue (declared as
Double) to a value > MaxSingle: Floating point overflow.
(See https://gitlab.com/freepascal.org/lazarus/lazarus/-/issues/39792)
The backtrace suggest that this happens in the function
MaxValueStored: this simply does:
function TCustomFloatSpinEdit.MaxValueStored: Boolean;
begin
Result := not SameValue(FMaxValue, DefMaxValue);
end;
DefMaxValue is declared as a private constant:
private const
DefMaxValue = 0;
The crash goes away if we do either of two things:
- in the call to SameValue typecast DefMaxValue to Double
- declare DefMaxValue as Double(0)
So far, so good.
But we also have a component TFloatSpinEditEx which is a generic
implementation of similar kind.
This component uses the same method for the MaxValueStored and thus
also crashed in the IDE.
So, I tried the same solution there: typecast DefMaxValue as
T(DefMaxValue) in the call to SameValue and then it turned out this
wouldn't compile on MacOS and Linux 64 bit.
--
Bart
More information about the fpc-devel
mailing list