unit tcOldObject5;
interface
uses
TestFrameWork
;
type
TtcOldObject5 = class(TTestCase)
published
procedure DoIt;
end;//TtcOldObject5
Tl3_PointUnion = packed record
Case Byte of
0: (X: Integer; Y: Integer);
end;//Tl3_PointUnion
TOldObject1 = object
private
P: Tl3_PointUnion;
public
property X: Integer
read P.X
write P.X;
end;//TOldObject1
function IntFunc(aValue: Integer): Integer;
function ObjFunc(const anObj: TOldObject1): Integer;
implementation
function IntFunc(aValue: Integer): Integer;
begin
Result := aValue;
end;//IntFunc
function ObjFunc(const anObj: TOldObject1): Integer;
begin
Result := IntFunc(anObj.X);
end;//IntFunc
procedure TtcOldObject5.DoIt;
const
cValue = 1024;
var
l_O1 : TOldObject1;
begin
l_O1.X := cValue;
Self.CheckTrue(l_O1.X = cValue);
Self.CheckTrue(IntFunc(l_O1.X) = cValue);
Self.CheckFalse(ObjFunc(l_O1) = cValue); // Ooops !
end;//TtcOldObject5.DoIt
initialization
TestFrameWork.RegisterTest(TtcOldObject5.Suite);
end.
Блог человека, который 18-ть лет программирует на Delphi. И 25 лет программирует вообще. VCL, UML, MDA, тесты. Это не "учебник", это - "заметки на полях".
среда, 21 октября 2020 г.
#872. Another compilation bug in Sydney under 64 bit
вторник, 20 октября 2020 г.
#871. Compilation bug in Sydney under 64 bit
https://quality.embarcadero.com/browse/RSP-31389
Code with bug:
Code with bug:
unit tcOldObject1; interface uses TestFrameWork ; type TtcOldObject1 = class(TTestCase) published procedure DoIt; end;//TtcOldObject1 TOldObject1 = object public rF: Pointer; end;//TOldObject1 TOldObject2 = object public rF: TOldObject1; end;//TOldObject2 function TOldObject2_C(const anObj: TOldObject1): TOldObject2; implementation function TOldObject2_C(const anObj: TOldObject1): TOldObject2; begin // - here lost pointer dereference // Compiler makes the code: (* push rbp sub rsp,$10 mov rbp,rsp mov [rbp+$20],rcx mov rax,[rbp+$20] mov [rbp+$08],rax mov rax,[rbp+$08] lea rsp,[rbp+$10] pop rbp ret *) // But the correct one is: (* push rbp sub rsp,$10 mov rbp,rsp mov [rbp+$20],rcx mov rax,[rbp+$20] mov rax,[rax] mov [rbp+$08],rax mov rax,[rbp+$08] lea rsp,[rbp+$10] pop rbp ret *) // Lost instruction: (* mov rax,[rax] *) // - dereference pointer to anObj lost !!! Result.rF := anObj; end;//TOldObject2_C procedure TtcOldObject1.DoIt; var l_O1 : TOldObject1; l_O2 : TOldObject2; begin l_O1.rF := TypeInfo(Integer); l_O2.rF := l_O1; Self.Check(l_O2.rF.rF = l_O1.rF); // Right ! l_O2 := TOldObject2_C(l_O1); Self.CheckFalse(l_O2.rF.rF = l_O1.rF); // Ooops ! Self.CheckTrue(l_O2.rF.rF = @l_O1.rF); // Ooops ! end;//TtcOldObject1.DoIt initialization TestFrameWork.RegisterTest(TtcOldObject1.Suite); end.Code without bug:
unit tcRecord1; interface uses TestFrameWork ; type TtcRecord1 = class(TTestCase) published procedure DoIt; end;//TtcRecord1 TRecord1 = record public rF: Pointer; end;//TRecord1 TRecord2 = record public rF: TRecord1; end;//TRecord2 function TRecord2_C(const anObj: TRecord1): TRecord2; implementation function TRecord2_C(const anObj: TRecord1): TRecord2; begin Result.rF := anObj; end;//TRecord2_C procedure TtcRecord1.DoIt; var l_O1 : TRecord1; l_O2 : TRecord2; begin l_O1.rF := TypeInfo(Integer); l_O2.rF := l_O1; Self.Check(l_O2.rF.rF = l_O1.rF); // Right ! l_O2 := TRecord2_C(l_O1); Self.CheckTrue(l_O2.rF.rF = l_O1.rF); // Right ! Self.CheckFalse(l_O2.rF.rF = @l_O1.rF); // Right ! end;//TtcRecord1.DoIt initialization TestFrameWork.RegisterTest(TtcRecord1.Suite); end.
Подписаться на:
Комментарии (Atom)