LazDebuggerFp, FpDebug: Enable watch-eval calling functions with records as param (Win-64/32 / Linux-64)

This commit is contained in:
Martin 2022-06-21 00:27:29 +02:00
parent b014798858
commit f606986f1b
5 changed files with 778 additions and 3 deletions

View File

@ -53,12 +53,14 @@ type
FLastError: TFpError;
FNextParamRegister: Integer;
FOrigStackPtr: TDBGPtr;
FPreparedStack: Array of Byte;
FNeedStringResInFinalize: Boolean;
FStringResultMem: TDBGPtr;
function AllocStack(ASize: Integer): TDbgPtr;
function InternalCreateParamSymbol(ParameterMemLocation: TFpDbgMemLocation; ASymbolType: TFpSymbol; AName: String): TFpValue;
function InternalCreateParamSymbol(AParamIndex: Integer; ASymbolType: TFpSymbol; AName: String): TFpValue; inline;
function AddRecordParam(var ParamSymbol: TFpValue; AParamSymbolType: TFpSymbol; AValue: TFpValue): Boolean;
function InternalAddStringResult: Boolean;
public
constructor Create(const ABaseContext: TFpDbgLocationContext;
@ -67,6 +69,7 @@ type
ADbgProcess: TDbgProcess;
ADbgThread: TDbgThread);
destructor Destroy; override;
function WriteStack: Boolean; // called by controller-command
function CreateParamSymbol(AParamIndex: Integer; ASymbolType: TFpSymbol; AName: String = ''): TFpValue; virtual;
@ -187,6 +190,148 @@ begin
ASymbolType, AName);
end;
function TFpDbgInfoCallContext.AddRecordParam(var ParamSymbol: TFpValue;
AParamSymbolType: TFpSymbol; AValue: TFpValue): Boolean;
// Only intel/amd
function ReadRecFromMem(Addr: TDbgPtr; sz: Integer; out Data: QWord): Boolean;
var
d: QWord;
begin
Result := FDbgProcess.ReadData(addr, sz, d);
if Result then begin
Data := 0;
Move(d, Data, sz);
end
else begin
FLastError := CreateError(fpErrAnyError, ['failed to read mem']);
end;
end;
function HasUnalignedFields: Boolean;
var
i: Integer;
FldLoc: TFpDbgMemLocation;
FldSize: TFpDbgValueSize;
RecAddr, FldOffs: TDBGPtr;
begin
Result := False;
RecAddr := AValue.Address.Address;
for i := 0 to AValue.MemberCount - 1 do begin
FldLoc := AValue.Member[i].Address;
Result := FldLoc.BitOffset <> 0;
if Result then
break;
FldOffs := FldLoc.Address - RecAddr;
FldSize := AValue.Member[i].DataSize;
Result := FldSize.BitSize <> 0;
if Result then
break;
Result := FldOffs mod FldSize.Size <> 0;
if Result then
break;
end;
end;
var
RecSize, i: Integer;
RecLoc: TFpDbgMemLocation;
RecAddr, RecData: TDBGPtr;
l: SizeInt;
begin
HasUnalignedFields;
RecSize := SizeToFullBytes(AValue.DataSize);
Result := not IsError(AValue.LastError);
if Result then begin
RecLoc := AValue.Address;
Result := IsValidLoc(RecLoc);
RecAddr := RecLoc.Address;
end;
if not Result then begin
FLastError := AValue.LastError;
exit;
end;
{$IF defined(WINDOWS)}
if FDbgProcess.Mode = dm32 then begin
if (RecSize <= FDbgProcess.PointerSize) then begin
Result := ReadRecFromMem(RecAddr, RecSize, RecData);
if not Result then
exit;
l := Length(FPreparedStack);
SetLength(FPreparedStack, l + 4);
if l > 0 then
move(FPreparedStack[0], FPreparedStack[4], SizeOf(FPreparedStack[0]) * l);
PDWord(@FPreparedStack[0])^ := RecData;
dec(FNextParamRegister); // no register used
exit;
end;
ParamSymbol.AsCardinal := RecAddr;
Result := not IsError(ParamSymbol.LastError);
FLastError := ParamSymbol.LastError;
end
else begin
if (RecSize <= FDbgProcess.PointerSize) and (RecSize in [2,4,8]) then begin
Result := ReadRecFromMem(RecAddr, RecSize, RecData);
RecAddr := RecData;
end;
if Result then begin
ParamSymbol.AsCardinal := RecAddr;
Result := not IsError(ParamSymbol.LastError);
FLastError := ParamSymbol.LastError;
end;
end;
{$ElseIf defined(UNIX)}
if FDbgProcess.Mode = dm64 then begin
if (RecSize <= 16) and not HasUnalignedFields then begin
// Use 1 or 2 registers
While RecSize > 0 do begin
Result := ReadRecFromMem(RecAddr, Min(8, RecSize), RecData);
if not Result then
exit;
ParamSymbol.AsCardinal := RecData;
Result := not IsError(ParamSymbol.LastError);
if not result then begin
FLastError := ParamSymbol.LastError;
exit;
end;
dec(RecSize, 8);
inc(RecAddr, 8);
if RecSize > 0 then begin
inc(FNextParamRegister);
ParamSymbol.ReleaseReference;
ParamSymbol := InternalCreateParamSymbol(FNextParamRegister, AParamSymbolType, '');
end;
end;
end
else begin
// on the stack
dec(FNextParamRegister); // no register used
i := (RecSize+7) and $FFFFFFF8;
l := Length(FPreparedStack);
SetLength(FPreparedStack, l + i);
Result := FDbgProcess.ReadData(RecAddr, RecSize, FPreparedStack[l]);
if not Result then begin
FLastError := CreateError(fpErrAnyError, ['failed to read mem']);
exit;
end;
end;
end
else begin
// 32bit linux
Result := False;
FLastError := CreateError(fpErrAnyError, ['not supported']);
end;
{$Else}
Result := False;
FLastError := CreateError(fpErrAnyError, ['not supported']);
{$ENDIF}
end;
function TFpDbgInfoCallContext.InternalAddStringResult: Boolean;
var
ParamSymbol: TFpValue;
@ -227,6 +372,19 @@ begin
FDbgThread.SetStackPointerRegisterValue(FOrigStackPtr);
end;
function TFpDbgInfoCallContext.WriteStack: Boolean;
var
m: TDBGPtr;
begin
if Length(FPreparedStack) = 0 then
exit;
m := AllocStack(Length(FPreparedStack));
Result := FDbgProcess.WriteData(m, Length(FPreparedStack), FPreparedStack[0]);
if not Result then
FLastError := CreateError(fpErrAnyError, ['failed to read mem']);
end;
function TFpDbgInfoCallContext.CreateParamSymbol(AParamIndex: Integer;
ASymbolType: TFpSymbol; AName: String): TFpValue;
begin
@ -245,7 +403,10 @@ begin
if not Result then
exit;
try
ParamSymbol.AsCardinal := AValue.AsCardinal;
if AValue.Kind = skRecord then
Result := AddRecordParam(ParamSymbol, AParamSymbolType, AValue)
else
ParamSymbol.AsCardinal := AValue.AsCardinal;
Result := not IsError(ParamSymbol.LastError);
FLastError := ParamSymbol.LastError;
finally

View File

@ -458,6 +458,8 @@ procedure TDbgControllerCallRoutineCmd.Init;
begin
inherited Init;
FCallContext.WriteStack;
FStep := sSingleStep;
StoreInstructionPointer;
InsertCallInstructionCode;

View File

@ -902,7 +902,7 @@ begin
end;
rk := ExprParamVal.Kind;
if not(
(rk in [skInteger, {skCurrency,} skPointer, skEnum, skCardinal, skBoolean, skChar, skClass]) or
(rk in [skInteger, {skCurrency,} skPointer, skEnum, skCardinal, skBoolean, skChar, skClass, skRecord]) or
( (rk in [skString, skAnsiString, skWideString]) and (ExprParamVal.FieldFlags * [svfAddress, svfDataAddress] <> []) )
)
then begin

View File

@ -0,0 +1,332 @@
program WatchesFuncRecordPrg;
{$mode objfpc}{$H+}
uses SysUtils;
type
TNibble = 0..15;
{$IFDEF RECPAD2}
TPad = word;
{$ELSE}
TPad = byte;
{$ENDIF}
TRecN2 = {$IFDEF PCKREC} packed {$ENDIF} record {$IFDEF RECPAD1} xxx: TPad; {$ENDIF} a, b: TNibble; end;
TRecB2 = {$IFDEF PCKREC} packed {$ENDIF} record {$IFDEF RECPAD1} xxx: TPad; {$ENDIF} a, b: Byte; end;
TRecW2 = {$IFDEF PCKREC} packed {$ENDIF} record {$IFDEF RECPAD1} xxx: TPad; {$ENDIF} a, b: Word; end;
TRecC2 = {$IFDEF PCKREC} packed {$ENDIF} record {$IFDEF RECPAD1} xxx: TPad; {$ENDIF} a, b: Cardinal; end;
TRecQ2 = {$IFDEF PCKREC} packed {$ENDIF} record {$IFDEF RECPAD1} xxx: TPad; {$ENDIF} a, b: QWord; end;
TRecB3 = {$IFDEF PCKREC} packed {$ENDIF} record {$IFDEF RECPAD1} xxx: TPad; {$ENDIF} a, b, c: Byte; end;
TRecW3 = {$IFDEF PCKREC} packed {$ENDIF} record {$IFDEF RECPAD1} xxx: TPad; {$ENDIF} a, b, c: Word; end;
TRecC3 = {$IFDEF PCKREC} packed {$ENDIF} record {$IFDEF RECPAD1} xxx: TPad; {$ENDIF} a, b, c: Cardinal; end;
TRecQ3 = {$IFDEF PCKREC} packed {$ENDIF} record {$IFDEF RECPAD1} xxx: TPad; {$ENDIF} a, b, c: QWord; end;
TRecQ4 = {$IFDEF PCKREC} packed {$ENDIF} record {$IFDEF RECPAD1} xxx: TPad; {$ENDIF} a, b, c, d: QWord; end;
TRecQ5 = {$IFDEF PCKREC} packed {$ENDIF} record {$IFDEF RECPAD1} xxx: TPad; {$ENDIF} a, b, c, d ,e: QWord; end;
TRecQ6 = {$IFDEF PCKREC} packed {$ENDIF} record {$IFDEF RECPAD1} xxx: TPad; {$ENDIF} a, b, c, d ,e, f: QWord; end;
TRecQ7 = {$IFDEF PCKREC} packed {$ENDIF} record {$IFDEF RECPAD1} xxx: TPad; {$ENDIF} a, b, c, d ,e, f, g: QWord; end;
var
CurMemUsed: ptruint;
SomeInt: Integer;
aRecN2, bRecN2: TRecN2;
aRecB2, bRecB2: TRecB2;
aRecW2, bRecW2: TRecW2;
aRecC2, bRecC2: TRecC2;
aRecQ2, bRecQ2: TRecQ2;
aRecB3, bRecB3: TRecB3;
aRecW3, bRecW3: TRecW3;
aRecC3, bRecC3: TRecC3;
aRecQ3, bRecQ3: TRecQ3;
aRecQ4, bRecQ4: TRecQ4;
aRecQ5, bRecQ5: TRecQ5;
aRecQ6, bRecQ6: TRecQ6;
aRecQ7, bRecQ7: TRecQ7;
function TestRecN2_a(AVal: TRecN2): Cardinal; begin Result := AVal.a; AVal.a:=0; end;
function TestRecN2_b(AVal: TRecN2): Cardinal; begin Result := AVal.b; AVal.a:=0; end;
function TestRecB2_a(AVal: TRecB2): Cardinal; begin Result := AVal.a; AVal.a:=0; end;
function TestRecB2_b(AVal: TRecB2): Cardinal; begin Result := AVal.b; AVal.a:=0; end;
function TestRecB3_a(AVal: TRecB3): Cardinal; begin Result := AVal.a; AVal.a:=0; end;
function TestRecB3_b(AVal: TRecB3): Cardinal; begin Result := AVal.b; AVal.a:=0; end;
function TestRecB3_c(AVal: TRecB3): Cardinal; begin Result := AVal.c; AVal.a:=0; end;
function TestRecW2_a(AVal: TRecW2): Cardinal; begin Result := AVal.a; AVal.a:=0; end;
function TestRecW2_b(AVal: TRecW2): Cardinal; begin Result := AVal.b; AVal.a:=0; end;
function TestRecW3_a(AVal: TRecW3): Cardinal; begin Result := AVal.a; AVal.a:=0; end;
function TestRecW3_b(AVal: TRecW3): Cardinal; begin Result := AVal.b; AVal.a:=0; end;
function TestRecW3_c(AVal: TRecW3): Cardinal; begin Result := AVal.c; AVal.a:=0; end;
function TestRecC2_a(AVal: TRecC2): Cardinal; begin Result := AVal.a; AVal.a:=0; end;
function TestRecC2_b(AVal: TRecC2): Cardinal; begin Result := AVal.b; AVal.a:=0; end;
function TestRecC3_a(AVal: TRecC3): Cardinal; begin Result := AVal.a; AVal.a:=0; end;
function TestRecC3_b(AVal: TRecC3): Cardinal; begin Result := AVal.b; AVal.a:=0; end;
function TestRecC3_c(AVal: TRecC3): Cardinal; begin Result := AVal.c; AVal.a:=0; end;
function TestRecQ2_a(AVal: TRecQ2): Cardinal; begin Result := AVal.a; AVal.a:=0; end;
function TestRecQ2_b(AVal: TRecQ2): Cardinal; begin Result := AVal.b; AVal.a:=0; end;
function TestRecQ3_a(AVal: TRecQ3): Cardinal; begin Result := AVal.a; AVal.a:=0; end;
function TestRecQ3_b(AVal: TRecQ3): Cardinal; begin Result := AVal.b; AVal.a:=0; end;
function TestRecQ3_c(AVal: TRecQ3): Cardinal; begin Result := AVal.c; AVal.a:=0; end;
function Test1RecB2(AVal: TRecB2; i: byte): Cardinal; begin if i=0 then Result := AVal.a else Result := AVal.b; AVal.a:=0; end;
function Test1RecW2(AVal: TRecW2; i: byte): Cardinal; begin if i=0 then Result := AVal.a else Result := AVal.b; AVal.a:=0; end;
function Test1RecC2(AVal: TRecC2; i: byte): Cardinal; begin if i=0 then Result := AVal.a else Result := AVal.b; AVal.a:=0; end;
function Test1RecQ2(AVal: TRecQ2; i: byte): Cardinal; begin if i=0 then Result := AVal.a else Result := AVal.b; AVal.a:=0; end;
function Test2RecB2(i: word; AVal: TRecB2): Cardinal; begin if i=0 then Result := AVal.a else Result := AVal.b; AVal.a:=0; end;
function Test2RecW2(i: word; AVal: TRecW2): Cardinal; begin if i=0 then Result := AVal.a else Result := AVal.b; AVal.a:=0; end;
function Test2RecC2(i: word; AVal: TRecC2): Cardinal; begin if i=0 then Result := AVal.a else Result := AVal.b; AVal.a:=0; end;
function Test2RecQ2(i: word; AVal: TRecQ2): Cardinal; begin if i=0 then Result := AVal.a else Result := AVal.b; AVal.a:=0; end;
function TestRecN2N2_1(AVal, BVal: TRecN2): Cardinal; begin Result := AVal.a; AVal.a:=0; end;
function TestRecN2N2_2(AVal, BVal: TRecN2): Cardinal; begin Result := BVal.a; AVal.a:=0; end;
function TestRecB2B2_1(AVal, BVal: TRecB2): Cardinal; begin Result := AVal.a; AVal.a:=0; end;
function TestRecB2B2_2(AVal, BVal: TRecB2): Cardinal; begin Result := BVal.a; AVal.a:=0; end;
function TestRecW2W2_1(AVal, BVal: TRecW2): Cardinal; begin Result := AVal.a; AVal.a:=0; end;
function TestRecW2W2_2(AVal, BVal: TRecW2): Cardinal; begin Result := BVal.a; AVal.a:=0; end;
function TestRecC2C2_1(AVal, BVal: TRecC2): Cardinal; begin Result := AVal.a; AVal.a:=0; end;
function TestRecC2C2_2(AVal, BVal: TRecC2): Cardinal; begin Result := BVal.a; AVal.a:=0; end;
function TestRecQ2Q2_1(AVal, BVal: TRecQ2): Cardinal; begin Result := AVal.a; AVal.a:=0; end;
function TestRecQ2Q2_2(AVal, BVal: TRecQ2): Cardinal; begin Result := BVal.a; AVal.a:=0; end;
function Test1RecB2B2(AVal, BVal: TRecB2; i: byte): Cardinal; begin if i=0 then Result := AVal.a else Result := BVal.a; AVal.a:=0; end;
function Test1RecW2W2(AVal, BVal: TRecW2; i: byte): Cardinal; begin if i=0 then Result := AVal.a else Result := BVal.a; AVal.a:=0; end;
function Test1RecC2C2(AVal, BVal: TRecC2; i: byte): Cardinal; begin if i=0 then Result := AVal.a else Result := BVal.a; AVal.a:=0; end;
function Test1RecQ2Q2(AVal, BVal: TRecQ2; i: byte): Cardinal; begin if i=0 then Result := AVal.a else Result := BVal.a; AVal.a:=0; end;
function Test2RecB2B2(i: word; AVal, BVal: TRecB2): Cardinal; begin if i=0 then Result := AVal.a else Result := BVal.a; AVal.a:=0; end;
function Test2RecW2W2(i: word; AVal, BVal: TRecW2): Cardinal; begin if i=0 then Result := AVal.a else Result := BVal.a; AVal.a:=0; end;
function Test2RecC2C2(i: word; AVal, BVal: TRecC2): Cardinal; begin if i=0 then Result := AVal.a else Result := BVal.a; AVal.a:=0; end;
function Test2RecQ2Q2(i: word; AVal, BVal: TRecQ2): Cardinal; begin if i=0 then Result := AVal.a else Result := BVal.a; AVal.a:=0; end;
function TestRecB2B3_1(AVal: TRecB2; BVal: TRecB3): Cardinal; begin Result := AVal.a; AVal.a:=0; end;
function TestRecB2Q2_1(AVal: TRecB2; BVal: TRecQ2): Cardinal; begin Result := AVal.a; AVal.a:=0; end;
function TestRecB3B2_1(AVal: TRecB3; BVal: TRecB2): Cardinal; begin Result := AVal.a; AVal.a:=0; end;
function TestRecB3Q2_1(AVal: TRecB3; BVal: TRecQ2): Cardinal; begin Result := AVal.a; AVal.a:=0; end;
function TestRecQ2B2_1(AVal: TRecQ2; BVal: TRecB2): Cardinal; begin Result := AVal.a; AVal.a:=0; end;
function TestRecQ2B3_1(AVal: TRecQ2; BVal: TRecB3): Cardinal; begin Result := AVal.a; AVal.a:=0; end;
function TestRecB2B3_2(AVal: TRecB2; BVal: TRecB3): Cardinal; begin Result := BVal.a; AVal.a:=0; end;
function TestRecB2Q2_2(AVal: TRecB2; BVal: TRecQ2): Cardinal; begin Result := BVal.a; AVal.a:=0; end;
function TestRecB3B2_2(AVal: TRecB3; BVal: TRecB2): Cardinal; begin Result := BVal.a; AVal.a:=0; end;
function TestRecB3Q2_2(AVal: TRecB3; BVal: TRecQ2): Cardinal; begin Result := BVal.a; AVal.a:=0; end;
function TestRecQ2B2_2(AVal: TRecQ2; BVal: TRecB2): Cardinal; begin Result := BVal.a; AVal.a:=0; end;
function TestRecQ2B3_2(AVal: TRecQ2; BVal: TRecB3): Cardinal; begin Result := BVal.a; AVal.a:=0; end;
function Test1RecB2B3(AVal: TRecB2; BVal: TRecB3; i: byte): Cardinal; begin if i=0 then Result := AVal.a else Result := BVal.a; AVal.a:=0; end;
function Test1RecB2Q2(AVal: TRecB2; BVal: TRecQ2; i: byte): Cardinal; begin if i=0 then Result := AVal.a else Result := BVal.a; AVal.a:=0; end;
function Test1RecB3B2(AVal: TRecB3; BVal: TRecB2; i: byte): Cardinal; begin if i=0 then Result := AVal.a else Result := BVal.a; AVal.a:=0; end;
function Test1RecB3Q2(AVal: TRecB3; BVal: TRecQ2; i: byte): Cardinal; begin if i=0 then Result := AVal.a else Result := BVal.a; AVal.a:=0; end;
function Test1RecQ2B2(AVal: TRecQ2; BVal: TRecB2; i: byte): Cardinal; begin if i=0 then Result := AVal.a else Result := BVal.a; AVal.a:=0; end;
function Test1RecQ2B3(AVal: TRecQ2; BVal: TRecB3; i: byte): Cardinal; begin if i=0 then Result := AVal.a else Result := BVal.a; AVal.a:=0; end;
function Test2RecB2B3(i: byte; AVal: TRecB2; BVal: TRecB3): Cardinal; begin if i=0 then Result := AVal.a else Result := BVal.a; AVal.a:=0; end;
function Test2RecB2Q2(i: byte; AVal: TRecB2; BVal: TRecQ2): Cardinal; begin if i=0 then Result := AVal.a else Result := BVal.a; AVal.a:=0; end;
function Test2RecB3B2(i: byte; AVal: TRecB3; BVal: TRecB2): Cardinal; begin if i=0 then Result := AVal.a else Result := BVal.a; AVal.a:=0; end;
function Test2RecB3Q2(i: byte; AVal: TRecB3; BVal: TRecQ2): Cardinal; begin if i=0 then Result := AVal.a else Result := BVal.a; AVal.a:=0; end;
function Test2RecQ2B2(i: byte; AVal: TRecQ2; BVal: TRecB2): Cardinal; begin if i=0 then Result := AVal.a else Result := BVal.a; AVal.a:=0; end;
function Test2RecQ2B3(i: byte; AVal: TRecQ2; BVal: TRecB3): Cardinal; begin if i=0 then Result := AVal.a else Result := BVal.a; AVal.a:=0; end;
function Test2RecQ3Q3(i: byte; AVal, BVal: TRecQ3): Cardinal;
begin
case i of
0: Result := AVal.a; 1: Result := AVal.c;
2: Result := BVal.a; 3: Result := BVal.c;
end;
AVal.a:=0; BVal.a:=0;
end;
function Test2RecQ4Q4(i: byte; AVal, BVal: TRecQ4): Cardinal;
begin
case i of
0: Result := AVal.a; 1: Result := AVal.d;
2: Result := BVal.a; 3: Result := BVal.d;
end;
AVal.a:=0; BVal.a:=0;
end;
function Test2RecQ5Q5(i: byte; AVal, BVal: TRecQ5): Cardinal;
begin
case i of
0: Result := AVal.a; 1: Result := AVal.e;
2: Result := BVal.a; 3: Result := BVal.e;
end;
AVal.a:=0; BVal.a:=0;
end;
function Test2RecQ6Q6(i: byte; AVal, BVal: TRecQ6): Cardinal;
begin
case i of
0: Result := AVal.a; 1: Result := AVal.f;
2: Result := BVal.a; 3: Result := BVal.f;
end;
AVal.a:=0; BVal.a:=0;
end;
function Test2RecQ7Q7(i: byte; AVal, BVal: TRecQ7): Cardinal;
begin
case i of
0: Result := AVal.a; 1: Result := AVal.g;
2: Result := BVal.a; 3: Result := BVal.g;
end;
AVal.a:=0; BVal.a:=0;
end;
function UsedMem: ptruint;
var
mm: TMemoryManager;
hs: TFPCHeapStatus;
begin
// ensure global vars are in mem
TestRecB2_a(aRecB2); TestRecB2_a(bRecB2);
TestRecB3_a(aRecB3); TestRecB3_a(bRecB3);
TestRecW2_a(aRecW2); TestRecW2_a(bRecW2);
TestRecW3_c(aRecW3); TestRecW3_c(bRecW3);
TestRecC2_a(aRecC2); TestRecC2_a(bRecC2);
TestRecC3_c(aRecC3); TestRecC3_c(bRecC3);
TestRecQ2_a(aRecQ2); TestRecQ2_a(bRecQ2);
TestRecQ3_c(aRecQ3); TestRecQ3_c(bRecQ3);
GetMemoryManager(mm);
hs := mm.GetFPCHeapStatus();
Result := hs.CurrHeapUsed;
end;
begin
aRecN2.a := 11; aRecN2.b := 12;
bRecN2.a := 8; bRecN2.b := 9;
aRecB2.a := 11; aRecB2.b := 21;
aRecW2.a := 12; aRecW2.b := 22;
aRecC2.a := 13; aRecC2.b := 23;
aRecQ2.a := 14; aRecQ2.b := 24;
bRecB2.a := 51; bRecB2.b := 61;
bRecW2.a := 52; bRecW2.b := 62;
bRecC2.a := 53; bRecC2.b := 63;
bRecQ2.a := 54; bRecQ2.b := 64;
aRecB3.a := 15; aRecB3.b := 25; aRecB3.c := 35;
aRecW3.a := 16; aRecW3.b := 26; aRecW3.c := 36;
aRecC3.a := 17; aRecC3.b := 27; aRecC3.c := 37;
aRecQ3.a := 18; aRecQ3.b := 28; aRecQ3.c := 38;
bRecB3.a := 55; bRecB3.b := 65; bRecB3.c := 75;
bRecW3.a := 56; bRecW3.b := 66; bRecW3.c := 76;
bRecC3.a := 57; bRecC3.b := 67; bRecC3.c := 77;
bRecQ3.a := 58; bRecQ3.b := 68; bRecQ3.c := 78;
aRecQ4.a := 58; aRecQ4.b := 68; aRecQ4.c := 78; aRecQ4.d := 2;
aRecQ5.a := 58; aRecQ5.b := 68; aRecQ5.c := 78; aRecQ5.d := 2; aRecQ5.e := 3;
aRecQ6.a := 58; aRecQ6.b := 68; aRecQ6.c := 78; aRecQ6.d := 2; aRecQ6.e := 3; aRecQ6.f := 4;
aRecQ7.a := 58; aRecQ7.b := 68; aRecQ7.c := 78; aRecQ7.d := 2; aRecQ7.e := 3; aRecQ7.f := 4; aRecQ7.g := 5;
bRecQ4.a := 59; bRecQ4.b := 69; bRecQ4.c := 79; bRecQ4.d := 92;
bRecQ5.a := 59; bRecQ5.b := 69; bRecQ5.c := 79; bRecQ5.d := 92; bRecQ5.e := 93;
bRecQ6.a := 59; bRecQ6.b := 69; bRecQ6.c := 79; bRecQ6.d := 92; bRecQ6.e := 93; bRecQ6.f := 94;
bRecQ7.a := 59; bRecQ7.b := 69; bRecQ7.c := 79; bRecQ7.d := 92; bRecQ7.e := 93; bRecQ7.f := 94; bRecQ7.g := 95;
// After each test the debugger can check the memusage
CurMemUsed := UsedMem;
CurMemUsed := UsedMem; // TEST_BREAKPOINT=main
CurMemUsed := UsedMem;
CurMemUsed := UsedMem;
CurMemUsed := UsedMem;
CurMemUsed := UsedMem;
CurMemUsed := UsedMem;
CurMemUsed := UsedMem;
TestRecN2_a(aRecN2);
TestRecN2_b(bRecN2);
TestRecB2_a(aRecB2);
TestRecB2_b(bRecB2);
TestRecB3_a(aRecB3);
TestRecB3_b(aRecB3);
TestRecB3_c(bRecB3);
TestRecW2_a(aRecW2);
TestRecW2_b(bRecW2);
TestRecW3_a(aRecW3);
TestRecW3_b(aRecW3);
TestRecW3_c(bRecW3);
TestRecC2_a(aRecC2);
TestRecC2_b(bRecC2);
TestRecC3_a(aRecC3);
TestRecC3_b(aRecC3);
TestRecC3_c(bRecC3);
TestRecQ2_a(aRecQ2);
TestRecQ2_b(bRecQ2);
TestRecQ3_a(aRecQ3);
TestRecQ3_b(aRecQ3);
TestRecQ3_c(bRecQ3);
Test1RecB2(aRecB2,1);
Test1RecW2(bRecW2,1);
Test1RecC2(aRecC2,1);
Test1RecQ2(aRecQ2,1);
Test2RecB2(1, aRecB2);
Test2RecW2(1, bRecW2);
Test2RecC2(1, aRecC2);
Test2RecQ2(1, aRecQ2);
TestRecN2N2_1(aRecN2, bRecN2); TestRecN2N2_2(aRecN2, bRecN2);
TestRecB2B2_1(aRecB2, bRecB2); TestRecB2B2_2(aRecB2, bRecB2);
TestRecW2W2_1(aRecW2, bRecW2); TestRecW2W2_2(aRecW2, bRecW2);
TestRecC2C2_1(aRecC2, bRecC2); TestRecC2C2_2(aRecC2, bRecC2);
TestRecQ2Q2_1(aRecQ2, bRecQ2); TestRecQ2Q2_2(aRecQ2, bRecQ2);
Test1RecB2B2(aRecB2, bRecB2,1);
Test1RecW2W2(aRecW2, bRecW2,1);
Test1RecC2C2(aRecC2, bRecC2,1);
Test1RecQ2Q2(aRecQ2, bRecQ2,1);
Test2RecB2B2(1,aRecB2, bRecB2);
Test2RecW2W2(1,aRecW2, bRecW2);
Test2RecC2C2(1,aRecC2, bRecC2);
Test2RecQ2Q2(1,aRecQ2, bRecQ2);
TestRecB2B3_1(aRecB2, bRecB3); TestRecB2B3_2(aRecB2, bRecB3);
TestRecB2Q2_1(aRecB2, bRecQ2); TestRecB2Q2_2(aRecB2, bRecQ2);
TestRecB3B2_1(aRecB3, bRecB2); TestRecB3B2_2(aRecB3, bRecB2);
TestRecB3Q2_1(aRecB3, bRecQ2); TestRecB3Q2_2(aRecB3, bRecQ2);
TestRecQ2B2_1(aRecQ2, bRecB2); TestRecQ2B2_2(aRecQ2, bRecB2);
TestRecQ2B3_1(aRecQ2, bRecB3); TestRecQ2B3_2(aRecQ2, bRecB3);
Test1RecB2B3(aRecB2, bRecB3, 1);
Test1RecB2Q2(aRecB2, bRecQ2, 1);
Test1RecB3B2(aRecB3, bRecB2, 1);
Test1RecB3Q2(aRecB3, bRecQ2, 1);
Test1RecQ2B2(aRecQ2, bRecB2, 1);
Test1RecQ2B3(aRecQ2, bRecB3, 1);
Test2RecB2B3(1, aRecB2, bRecB3);
Test2RecB2Q2(1, aRecB2, bRecQ2);
Test2RecB3B2(1, aRecB3, bRecB2);
Test2RecB3Q2(1, aRecB3, bRecQ2);
Test2RecQ2B2(1, aRecQ2, bRecB2);
Test2RecQ2B3(1, aRecQ2, bRecB3);
Test2RecQ3Q3(1, aRecQ3, bRecQ3);
Test2RecQ4Q4(1, aRecQ4, bRecQ4);
Test2RecQ5Q5(1, aRecQ5, bRecQ5);
Test2RecQ6Q6(1, aRecQ6, bRecQ6);
Test2RecQ7Q7(1, aRecQ7, bRecQ7);
end.

View File

@ -26,6 +26,7 @@ type
procedure TestWatchesValue;
procedure TestWatchesFunctions;
procedure TestWatchesFunctionsWithString;
procedure TestWatchesFunctionsWithRecord;
procedure TestWatchesAddressOf;
procedure TestWatchesTypeCast;
procedure TestWatchesExpression;
@ -37,7 +38,8 @@ implementation
var
ControlTestWatch, ControlTestWatchScope, ControlTestWatchValue, ControlTestWatchFunct,
ControlTestWatchFunctStr, ControlTestWatchAddressOf, ControlTestWatchTypeCast, ControlTestModify,
ControlTestWatchFunctStr, ControlTestWatchFunctRec,
ControlTestWatchAddressOf, ControlTestWatchTypeCast, ControlTestModify,
ControlTestExpression, ControlTestErrors: Pointer;
procedure TTestWatches.RunToPause(var ABrk: TDBGBreakPoint;
@ -1693,6 +1695,283 @@ begin
end;
procedure TTestWatches.TestWatchesFunctionsWithRecord;
var
ExeName, tbn: String;
t: TWatchExpectationList;
Src: TCommonSource;
BrkPrg: TDBGBreakPoint;
i, p: Integer;
begin
if SkipTest then exit;
if not TestControlCanTest(ControlTestWatchFunctRec) then exit;
//if not (Compiler.SymbolType in [stDwarf3, stDwarf4]) then exit;
//if Compiler.HasFlag('SkipStringFunc') then exit;
tbn := TestBaseName;
try
for p := 0 to 3 do
for i := 0 to 2 do begin
TestBaseName := tbn;
TestBaseName := TestBaseName + ' -O'+IntToStr(i) + ' (def: ' + IntToStr(p) + ')';
Src := GetCommonSourceFor(AppDir + 'WatchesFuncRecordPrg.pas');
case p of
0: case i of
0: TestCompile(Src, ExeName, '_O0', '-O-');
1: TestCompile(Src, ExeName, '_O1', '-O-1');
2: TestCompile(Src, ExeName, '_O2', '-O-2');
end;
1: case i of
0: TestCompile(Src, ExeName, '_O0_pack', '-dPCKREC -O-');
1: TestCompile(Src, ExeName, '_O1_pack', '-dPCKREC -O-1');
2: TestCompile(Src, ExeName, '_O2_pack', '-dPCKREC -O-2');
end;
2: case i of
0: TestCompile(Src, ExeName, '_O0_pack_padbyte', '-dPCKREC -dRECPAD1 -O-');
1: TestCompile(Src, ExeName, '_O1_pack_padbyte', '-dPCKREC -dRECPAD1 -O-1');
2: TestCompile(Src, ExeName, '_O2_pack_padbyte', '-dPCKREC -dRECPAD1 -O-2');
end;
3: case i of
0: TestCompile(Src, ExeName, '_O0_pack_padword', '-dPCKREC -dRECPAD1 -dRECPAD2 -O-');
1: TestCompile(Src, ExeName, '_O1_pack_padword', '-dPCKREC -dRECPAD1 -dRECPAD2 -O-1');
2: TestCompile(Src, ExeName, '_O2_pack_padword', '-dPCKREC -dRECPAD1 -dRECPAD2 -O-2');
end;
end;
t := nil;
AssertTrue('Start debugger', Debugger.StartDebugger(AppDir, ExeName));
try
t := TWatchExpectationList.Create(Self);
t.AcceptSkSimple := [skInteger, skCardinal, skBoolean, skChar, skFloat,
skString, skAnsiString, skCurrency, skVariant, skWideString,
skInterface, skEnumValue];
t.AddTypeNameAlias('integer', 'integer|longint');
BrkPrg := Debugger.SetBreakPoint(Src, 'main');
AssertDebuggerNotInErrorState;
(* ************ Nested Functions ************* *)
RunToPause(BrkPrg);
t.Clear;
t.Add('TestRecN2_a(aRecN2)', weCardinal(11)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecN2_b(aRecN2)', weCardinal(12)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecB2_a(aRecB2)', weCardinal(11)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecB2_b(aRecB2)', weCardinal(21)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecB2_a(bRecB2)', weCardinal(51)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecB2_b(bRecB2)', weCardinal(61)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('aRecB2.a', weCardinal(11, #1, -1)).IgnTypeName.SkipEval.IgnKind;
t.Add('bRecB2.a', weCardinal(51, #1, -1)).IgnTypeName.SkipEval.IgnKind;
t.Add('TestRecW2_a(aRecW2)', weCardinal(12)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecW2_b(aRecW2)', weCardinal(22)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecW2_a(bRecW2)', weCardinal(52)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecW2_b(bRecW2)', weCardinal(62)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('aRecW2.a', weCardinal(12, #1, -1)).IgnTypeName.SkipEval.IgnKind;
t.Add('bRecW2.a', weCardinal(52, #1, -1)).IgnTypeName.SkipEval.IgnKind;
t.Add('TestRecC2_a(aRecC2)', weCardinal(13)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecC2_b(aRecC2)', weCardinal(23)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecC2_a(bRecC2)', weCardinal(53)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecC2_b(bRecC2)', weCardinal(63)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('aRecC2.a', weCardinal(13, #1, -1)).IgnTypeName.SkipEval.IgnKind;
t.Add('bRecC2.a', weCardinal(53, #1, -1)).IgnTypeName.SkipEval.IgnKind;
t.Add('TestRecQ2_a(aRecQ2)', weCardinal(14)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecQ2_b(aRecQ2)', weCardinal(24)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecQ2_a(bRecQ2)', weCardinal(54)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecQ2_b(bRecQ2)', weCardinal(64)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('aRecQ2.a', weCardinal(14, #1, -1)).IgnTypeName.SkipEval.IgnKind;
t.Add('bRecQ2.a', weCardinal(54, #1, -1)).IgnTypeName.SkipEval.IgnKind;
t.Add('TestRecB3_a(aRecB3)', weCardinal(15)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecB3_c(aRecB3)', weCardinal(35)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('aRecB3.a', weCardinal(15, #1, -1)).IgnTypeName.SkipEval.IgnKind;
t.Add('TestRecW3_a(aRecW3)', weCardinal(16)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecW3_c(aRecW3)', weCardinal(36)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('aRecW3.a', weCardinal(16, #1, -1)).IgnTypeName.SkipEval.IgnKind;
t.Add('TestRecC3_a(aRecC3)', weCardinal(17)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecC3_c(aRecC3)', weCardinal(37)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('aRecC3.a', weCardinal(17, #1, -1)).IgnTypeName.SkipEval.IgnKind;
t.Add('TestRecQ3_a(aRecQ3)', weCardinal(18)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecQ3_c(aRecQ3)', weCardinal(38)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('aRecQ3.a', weCardinal(18, #1, -1)).IgnTypeName.SkipEval.IgnKind;
t.Add('Test1RecB2(aRecB2, 0)', weCardinal(11)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test1RecB2(aRecB2, 1)', weCardinal(21)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test1RecW2(aRecW2, 0)', weCardinal(12)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test1RecW2(aRecW2, 1)', weCardinal(22)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test1RecC2(aRecC2, 0)', weCardinal(13)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test1RecC2(aRecC2, 1)', weCardinal(23)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test1RecQ2(aRecQ2, 0)', weCardinal(14)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test1RecQ2(aRecQ2, 1)', weCardinal(24)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecB2(0, aRecB2)', weCardinal(11)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecB2(1, aRecB2)', weCardinal(21)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecW2(0, aRecW2)', weCardinal(12)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecW2(1, aRecW2)', weCardinal(22)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecC2(0, aRecC2)', weCardinal(13)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecC2(1, aRecC2)', weCardinal(23)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecQ2(0, aRecQ2)', weCardinal(14)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecQ2(1, aRecQ2)', weCardinal(24)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('aRecB2.a', weCardinal(11, #1, -1)).IgnTypeName.SkipEval.IgnKind;
t.Add('aRecW2.a', weCardinal(12, #1, -1)).IgnTypeName.SkipEval.IgnKind;
t.Add('aRecC2.a', weCardinal(13, #1, -1)).IgnTypeName.SkipEval.IgnKind;
t.Add('aRecQ2.a', weCardinal(14, #1, -1)).IgnTypeName.SkipEval.IgnKind;
t.Add('TestRecN2N2_1(aRecN2, bRecN2)', weCardinal(11)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecN2N2_2(aRecN2, bRecN2)', weCardinal(8)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecB2B2_1(aRecB2, bRecB2)', weCardinal(11)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecB2B2_2(aRecB2, bRecB2)', weCardinal(51)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecW2W2_1(aRecW2, bRecW2)', weCardinal(12)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecW2W2_2(aRecW2, bRecW2)', weCardinal(52)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecC2C2_1(aRecC2, bRecC2)', weCardinal(13)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecC2C2_2(aRecC2, bRecC2)', weCardinal(53)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecQ2Q2_1(aRecQ2, bRecQ2)', weCardinal(14)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecQ2Q2_2(aRecQ2, bRecQ2)', weCardinal(54)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test1RecB2B2(aRecB2, bRecB2, 0)', weCardinal(11)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test1RecB2B2(aRecB2, bRecB2, 1)', weCardinal(51)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test1RecW2W2(aRecW2, bRecW2, 0)', weCardinal(12)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test1RecW2W2(aRecW2, bRecW2, 1)', weCardinal(52)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test1RecC2C2(aRecC2, bRecC2, 0)', weCardinal(13)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test1RecC2C2(aRecC2, bRecC2, 1)', weCardinal(53)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test1RecQ2Q2(aRecQ2, bRecQ2, 0)', weCardinal(14)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test1RecQ2Q2(aRecQ2, bRecQ2, 1)', weCardinal(54)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecB2B2(0, aRecB2, bRecB2)', weCardinal(11)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecB2B2(1, aRecB2, bRecB2)', weCardinal(51)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecW2W2(0, aRecW2, bRecW2)', weCardinal(12)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecW2W2(1, aRecW2, bRecW2)', weCardinal(52)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecC2C2(0, aRecC2, bRecC2)', weCardinal(13)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecC2C2(1, aRecC2, bRecC2)', weCardinal(53)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecQ2Q2(0, aRecQ2, bRecQ2)', weCardinal(14)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecQ2Q2(1, aRecQ2, bRecQ2)', weCardinal(54)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('aRecB2.a', weCardinal(11, #1, -1)).IgnTypeName.SkipEval.IgnKind;
t.Add('aRecW2.a', weCardinal(12, #1, -1)).IgnTypeName.SkipEval.IgnKind;
t.Add('aRecC2.a', weCardinal(13, #1, -1)).IgnTypeName.SkipEval.IgnKind;
t.Add('aRecQ2.a', weCardinal(14, #1, -1)).IgnTypeName.SkipEval.IgnKind;
t.Add('bRecB2.a', weCardinal(51, #1, -1)).IgnTypeName.SkipEval.IgnKind;
t.Add('bRecW2.a', weCardinal(52, #1, -1)).IgnTypeName.SkipEval.IgnKind;
t.Add('bRecC2.a', weCardinal(53, #1, -1)).IgnTypeName.SkipEval.IgnKind;
t.Add('bRecQ2.a', weCardinal(54, #1, -1)).IgnTypeName.SkipEval.IgnKind;
t.Add('TestRecB2B3_1(aRecB2, bRecB3)', weCardinal(11)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecB2Q2_1(aRecB2, bRecQ2)', weCardinal(11)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecB3B2_1(aRecB3, bRecB2)', weCardinal(15)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecB3Q2_1(aRecB3, bRecQ2)', weCardinal(15)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecQ2B2_1(aRecQ2, bRecB2)', weCardinal(14)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecQ2B3_1(aRecQ2, bRecB3)', weCardinal(14)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecB2B3_2(aRecB2, bRecB3)', weCardinal(55)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecB2Q2_2(aRecB2, bRecQ2)', weCardinal(54)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecB3B2_2(aRecB3, bRecB2)', weCardinal(51)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecB3Q2_2(aRecB3, bRecQ2)', weCardinal(54)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecQ2B2_2(aRecQ2, bRecB2)', weCardinal(51)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('TestRecQ2B3_2(aRecQ2, bRecB3)', weCardinal(55)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test1RecB2B3(aRecB2, bRecB3, 0)', weCardinal(11)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test1RecB2Q2(aRecB2, bRecQ2, 0)', weCardinal(11)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test1RecB3B2(aRecB3, bRecB2, 0)', weCardinal(15)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test1RecB3Q2(aRecB3, bRecQ2, 0)', weCardinal(15)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test1RecQ2B2(aRecQ2, bRecB2, 0)', weCardinal(14)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test1RecQ2B3(aRecQ2, bRecB3, 0)', weCardinal(14)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test1RecB2B3(aRecB2, bRecB3, 1)', weCardinal(55)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test1RecB2Q2(aRecB2, bRecQ2, 1)', weCardinal(54)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test1RecB3B2(aRecB3, bRecB2, 1)', weCardinal(51)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test1RecB3Q2(aRecB3, bRecQ2, 1)', weCardinal(54)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test1RecQ2B2(aRecQ2, bRecB2, 1)', weCardinal(51)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test1RecQ2B3(aRecQ2, bRecB3, 1)', weCardinal(55)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecB2B3(0, aRecB2, bRecB3)', weCardinal(11)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecB2Q2(0, aRecB2, bRecQ2)', weCardinal(11)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecB3B2(0, aRecB3, bRecB2)', weCardinal(15)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecB3Q2(0, aRecB3, bRecQ2)', weCardinal(15)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecQ2B2(0, aRecQ2, bRecB2)', weCardinal(14)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecQ2B3(0, aRecQ2, bRecB3)', weCardinal(14)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecB2B3(1, aRecB2, bRecB3)', weCardinal(55)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecB2Q2(1, aRecB2, bRecQ2)', weCardinal(54)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecB3B2(1, aRecB3, bRecB2)', weCardinal(51)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecB3Q2(1, aRecB3, bRecQ2)', weCardinal(54)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecQ2B2(1, aRecQ2, bRecB2)', weCardinal(51)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecQ2B3(1, aRecQ2, bRecB3)', weCardinal(55)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecQ3Q3(0, aRecQ3, bRecQ3)', weCardinal(18)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecQ3Q3(1, aRecQ3, bRecQ3)', weCardinal(38)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecQ3Q3(2, aRecQ3, bRecQ3)', weCardinal(58)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecQ3Q3(3, aRecQ3, bRecQ3)', weCardinal(78)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecQ4Q4(0, aRecQ4, bRecQ4)', weCardinal(58)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecQ4Q4(1, aRecQ4, bRecQ4)', weCardinal( 2)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecQ4Q4(2, aRecQ4, bRecQ4)', weCardinal(59)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecQ4Q4(3, aRecQ4, bRecQ4)', weCardinal(92)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecQ5Q5(0, aRecQ5, bRecQ5)', weCardinal(58)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecQ5Q5(1, aRecQ5, bRecQ5)', weCardinal( 3)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecQ5Q5(2, aRecQ5, bRecQ5)', weCardinal(59)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecQ5Q5(3, aRecQ5, bRecQ5)', weCardinal(93)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecQ6Q6(0, aRecQ6, bRecQ6)', weCardinal(58)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecQ6Q6(1, aRecQ6, bRecQ6)', weCardinal( 4)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecQ6Q6(2, aRecQ6, bRecQ6)', weCardinal(59)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecQ6Q6(3, aRecQ6, bRecQ6)', weCardinal(94)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecQ7Q7(0, aRecQ7, bRecQ7)', weCardinal(58)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecQ7Q7(1, aRecQ7, bRecQ7)', weCardinal( 5)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecQ7Q7(2, aRecQ7, bRecQ7)', weCardinal(59)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('Test2RecQ7Q7(3, aRecQ7, bRecQ7)', weCardinal(95)).AddEvalFlag([defAllowFunctionCall]).IgnTypeName.SkipEval;
t.Add('aRecB2.a', weCardinal(11, #1, -1)).IgnTypeName.SkipEval.IgnKind;
t.Add('aRecW2.a', weCardinal(12, #1, -1)).IgnTypeName.SkipEval.IgnKind;
t.Add('aRecC2.a', weCardinal(13, #1, -1)).IgnTypeName.SkipEval.IgnKind;
t.Add('aRecQ2.a', weCardinal(14, #1, -1)).IgnTypeName.SkipEval.IgnKind;
t.Add('bRecB2.a', weCardinal(51, #1, -1)).IgnTypeName.SkipEval.IgnKind;
t.Add('bRecW2.a', weCardinal(52, #1, -1)).IgnTypeName.SkipEval.IgnKind;
t.Add('bRecC2.a', weCardinal(53, #1, -1)).IgnTypeName.SkipEval.IgnKind;
t.Add('bRecQ2.a', weCardinal(54, #1, -1)).IgnTypeName.SkipEval.IgnKind;
t.EvalAndCheck;
finally
Debugger.RunToNextPause(dcStop);
FreeAndNil(t);
Debugger.ClearDebuggerMonitors;
Debugger.FreeDebugger;
end;
end;
finally
AssertTestErrors;
end;
end;
procedure TTestWatches.TestWatchesAddressOf;
type
@ -3242,6 +3521,7 @@ initialization
ControlTestWatchValue := TestControlRegisterTest('Value', ControlTestWatch);
ControlTestWatchFunct := TestControlRegisterTest('Function', ControlTestWatch);
ControlTestWatchFunctStr := TestControlRegisterTest('FunctionString', ControlTestWatch);
ControlTestWatchFunctRec := TestControlRegisterTest('FunctionRecord', ControlTestWatch);
ControlTestWatchAddressOf := TestControlRegisterTest('AddressOf', ControlTestWatch);
ControlTestWatchTypeCast := TestControlRegisterTest('TypeCast', ControlTestWatch);
ControlTestModify := TestControlRegisterTest('Modify', ControlTestWatch);