FpDebug: fix array with struct / tests

git-svn-id: trunk@44531 -
This commit is contained in:
martin 2014-03-28 00:21:26 +00:00
parent fc89c8dc99
commit b9283584dc
8 changed files with 270 additions and 107 deletions

View File

@ -823,6 +823,7 @@ type
FDataAddressDone: Boolean; FDataAddressDone: Boolean;
protected protected
procedure Reset; override; procedure Reset; override;
procedure ClearMembers;
function GetFieldFlags: TFpDbgValueFieldFlags; override; function GetFieldFlags: TFpDbgValueFieldFlags; override;
function GetKind: TDbgSymbolKind; override; function GetKind: TDbgSymbolKind; override;
function GetAsCardinal: QWord; override; function GetAsCardinal: QWord; override;
@ -2565,6 +2566,16 @@ procedure TFpDbgDwarfValueStructTypeCast.Reset;
begin begin
inherited Reset; inherited Reset;
FDataAddressDone := False; FDataAddressDone := False;
ClearMembers;
end;
procedure TFpDbgDwarfValueStructTypeCast.ClearMembers;
var
i: Integer;
begin
if FMembers <> nil then
for i := 0 to FMembers.Count - 1 do
TDbgDwarfValueIdentifier(FMembers[i]).StructureValueInfo := nil;
end; end;
function TFpDbgDwarfValueStructTypeCast.GetFieldFlags: TFpDbgValueFieldFlags; function TFpDbgDwarfValueStructTypeCast.GetFieldFlags: TFpDbgValueFieldFlags;
@ -2679,12 +2690,8 @@ begin
end; end;
destructor TFpDbgDwarfValueStructTypeCast.Destroy; destructor TFpDbgDwarfValueStructTypeCast.Destroy;
var
i: Integer;
begin begin
if FMembers <> nil then ClearMembers;
for i := 0 to FMembers.Count - 1 do
TDbgDwarfValueIdentifier(FMembers[i]).StructureValueInfo := nil;
FreeAndNil(FMembers); FreeAndNil(FMembers);
inherited Destroy; inherited Destroy;
end; end;
@ -2717,6 +2724,7 @@ begin
if not HasTypeCastInfo then if not HasTypeCastInfo then
exit; exit;
// TODO: Why store them all in list? They are hold by the type
tmp := FTypeCastTargetType.Member[AIndex]; tmp := FTypeCastTargetType.Member[AIndex];
if (tmp <> nil) then begin if (tmp <> nil) then begin
assert((tmp is TDbgDwarfValueIdentifier), 'TDbgDwarfStructTypeCastSymbolValue.GetMemberByName'+DbgSName(tmp)); assert((tmp is TDbgDwarfValueIdentifier), 'TDbgDwarfStructTypeCastSymbolValue.GetMemberByName'+DbgSName(tmp));
@ -2857,6 +2865,9 @@ end;
procedure TFpDbgDwarfValue.SetStructureValue(AValue: TFpDbgDwarfValue); procedure TFpDbgDwarfValue.SetStructureValue(AValue: TFpDbgDwarfValue);
begin begin
if FStructureValue <> nil then
Reset;
if FStructureValue = AValue then if FStructureValue = AValue then
exit; exit;

View File

@ -1,11 +1,78 @@
unit TestWatchesUnitArray; unit TestWatchesUnitArray;
{$mode objfpc}{$H+}{$NOTES off}
interface interface
uses sysutils, types; uses sysutils, types;
procedure Test1; type
TArrayClass1 = class;
TArrayRec = packed record
FieldInt1, FieldInt2: Integer;
FieldDynInt1: array of Integer;
FieldStatInt1: array [4..9] of Integer;
FieldByte1: Byte;
end;
implementation TArrayDynInt = array of Integer;
TArrayDynClass = array of TArrayClass1;
TArrayDynRec = array of TArrayRec;
TArrayDynDynInt = array of array of Integer;
TArrayDynDynClass = array of array of TArrayClass1;
TArrayDynDynRec = array of array of TArrayRec;
TArrayDynStatInt = array of array [1..5] of Integer;
TArrayDynStatClass = array of array [1..5] of TArrayClass1;
TArrayDynStatRec = array of array [1..5] of TArrayRec;
TArrayStatInt = array [-2..5] of Integer;
TArrayStatClass = array [-2..5] of TArrayClass1;
TArrayStatRec = array [-2..5] of TArrayRec;
TArrayStatStatInt = array [-9..-5] of array [1..5] of Integer;
TArrayStatStatClass = array [-9..-5] of array [1..5] of TArrayClass1;
TArrayStatStatRec = array [-9..-5] of array [1..5] of TArrayRec;
TArrayStatDynInt = array [-9..-5] of array of Integer;
TArrayStatDynClass = array [-9..-5] of array of TArrayClass1;
TArrayStatDynRec = array [-9..-5] of array of TArrayRec;
{ TArrayClass1 }
TArrayClass1 = class
public
FieldInt1, FieldInt2: Integer;
FieldDynAInt1: array of Integer;
FieldStatAInt1: array [4..9] of Integer;
FieldDynInt1: TArrayDynInt;
FieldDynClass1: TArrayDynClass;
FieldDynRec1: TArrayDynRec;
FieldDynDynInt1: TArrayDynDynInt;
FieldDynDynClass1: TArrayDynDynClass;
FieldDynDynRec1: TArrayDynDynRec;
FieldDynStatInt1: TArrayDynStatInt;
FieldDynStatClass1: TArrayDynStatClass;
FieldDynStatRec1: TArrayDynStatRec;
FieldStatInt1: TArrayStatInt;
FieldStatClass1: TArrayStatClass;
FieldStatRec1: TArrayStatRec;
FieldStatStatInt1: TArrayStatStatInt;
FieldStatStatClass1: TArrayStatStatClass;
FieldStatStatRec1: TArrayStatStatRec;
FieldStatDynInt1: TArrayStatDynInt;
FieldStatDynClass1: TArrayStatDynClass;
FieldStatDynRec1: TArrayStatDynRec;
procedure Test1Method;
end;
var var
ArrayGlob_DynInt1, ArrayGlob_DynInt2: array of Integer; ArrayGlob_DynInt1, ArrayGlob_DynInt2: array of Integer;
@ -13,6 +80,12 @@ var
ArrayGlob_StatInt2: array [-4..9] of Integer; ArrayGlob_StatInt2: array [-4..9] of Integer;
procedure Test1; procedure Test1;
implementation
{ TArrayClass1 }
procedure TArrayClass1.Test1Method;
begin begin
ArrayGlob_DynInt2 := nil; ArrayGlob_DynInt2 := nil;
@ -37,8 +110,78 @@ begin
ArrayGlob_StatInt2[1] := 3305; ArrayGlob_StatInt2[1] := 3305;
ArrayGlob_DynInt1[9] := -5511; // BREAK SetLength(FieldDynInt1, 5);
FieldDynInt1[0] := 100;
FieldDynInt1[1] := 101;
FieldDynInt1[2] := 102;
SetLength(FieldDynClass1, 6);
FieldDynClass1[0] := TArrayClass1.Create;
FieldDynClass1[0].FieldInt1 := 98700;
FieldDynClass1[0].FieldInt2 := 98701;
SetLength(FieldDynClass1[0].FieldDynAInt1, 2);
FieldDynClass1[0].FieldDynAInt1[0] := 9900;
FieldDynClass1[0].FieldDynAInt1[1] := 9901;
FieldDynClass1[1] := TArrayClass1.Create;
FieldDynClass1[1].FieldInt1 := 88700;
FieldDynClass1[1].FieldInt2 := 88701;
SetLength(FieldDynClass1[1].FieldDynAInt1, 2);
FieldDynClass1[1].FieldDynAInt1[0] := 8900;
FieldDynClass1[1].FieldDynAInt1[1] := 8901;
FieldDynClass1[2] := TArrayClass1.Create;
FieldDynClass1[2].FieldInt1 := 78700;
FieldDynClass1[2].FieldInt2 := 78701;
SetLength(FieldDynClass1[2].FieldDynAInt1, 3);
FieldDynClass1[2].FieldDynAInt1[0] := 7900;
FieldDynClass1[2].FieldDynAInt1[1] := 7901;
FieldDynClass1[2].FieldDynAInt1[2] := 7902;
SetLength(FieldDynRec1, 7);
FieldDynRec1[0].FieldInt1 := 200;
FieldDynRec1[0].FieldInt2 := 201;
FieldDynRec1[1].FieldInt1 := 210;
FieldDynRec1[1].FieldInt2 := 211;
FieldDynRec1[2].FieldInt1 := 220;
FieldDynRec1[2].FieldInt2 := 221;
SetLength(FieldDynDynInt1, 5,3);
FieldDynDynInt1[0][0] := 1000;
FieldDynDynInt1[0][1] := 1001;
FieldDynDynInt1[0][2] := 1002;
FieldDynDynInt1[0][3] := 1003;
FieldDynDynInt1[1][0] := 1010;
FieldDynDynInt1[1][1] := 1011;
SetLength(FieldDynDynClass1, 5,4);
SetLength(FieldDynDynRec1, 5,6);
SetLength(FieldDynStatInt1, 3);
SetLength(FieldDynStatClass1, 4);
SetLength(FieldDynStatRec1, 5);
//SetLength(FieldStatInt1, );
//SetLength(FieldStatClass1, );
//SetLength(FieldStatRec1, );
//SetLength(FieldStatStatInt1, );
//SetLength(FieldStatStatClass1, );
//SetLength(FieldStatStatRec1, );
SetLength(FieldStatDynInt1[-9], 3);
SetLength(FieldStatDynClass1[-9], 3);
SetLength(FieldStatDynRec1[-9], 3);
ArrayGlob_DynInt1[9] := -5511; // BREAK
end;
procedure Test1;
var
ArrayClass1: TArrayClass1;
begin
ArrayClass1 := TArrayClass1.Create;
ArrayClass1.Test1Method;
end; end;
end. end.

View File

@ -1,4 +1,5 @@
unit TestWatchesUnitSimple; unit TestWatchesUnitSimple;
{$mode objfpc}{$H+}{$NOTES off}
interface interface
uses sysutils, types; uses sysutils, types;
@ -167,7 +168,10 @@ begin
SimpleGlob_QWord4 := high(QWord); SimpleGlob_QWord4 := high(QWord);
SimpleGlob_QWord5 := low(QWord); SimpleGlob_QWord5 := low(QWord);
SimpleGlob_Single1 := 99.2;
SimpleGlob_Double1 := 199.3;
SimpleGlob_Ext1 := 299.4;
SimpleGlob_Comp1 := -2;
SimplePArg_Int1 := @SimpleArg_Int1; SimplePArg_Int1 := @SimpleArg_Int1;

View File

@ -1,4 +1,5 @@
unit TestWatchesUnitStruct; unit TestWatchesUnitStruct;
{$mode objfpc}{$H+}{$NOTES off}
interface interface
uses sysutils, types; uses sysutils, types;

View File

@ -10,11 +10,11 @@ uses
GDBMIDebugger; GDBMIDebugger;
const const
BREAK_LINE_TestWatchesUnitSimple_1 = 178; BREAK_LINE_TestWatchesUnitSimple_1 = 182;
BREAK_LINE_TestWatchesUnitSimple_2 = 185; BREAK_LINE_TestWatchesUnitSimple_2 = 189;
BREAK_LINE_TestWatchesUnitSimple_3 = 192; BREAK_LINE_TestWatchesUnitSimple_3 = 196;
BREAK_LINE_TestWatchesUnitArray = 38; BREAK_LINE_TestWatchesUnitArray = 176;
type type
@ -25,11 +25,6 @@ type
FWatches: TWatches; FWatches: TWatches;
ExpectBreakSimple_1: TWatchExpectationArray; ExpectBreakSimple_1: TWatchExpectationArray;
FSimplePArg_Int1, FAddrSimpleArg_Int1,
FSimplePVArg_Int1, FAddrSimpleVArg_Int1,
FSimplePLocal_Int1, FAddrSimpleLocal_Int1,
FSimplePGlob_Int1, FAddrSimpleGlob_Int1: PWatchExpectation;
ExpectBreakSimple_2: TWatchExpectationArray; ExpectBreakSimple_2: TWatchExpectationArray;
ExpectBreakSimple_3: TWatchExpectationArray; ExpectBreakSimple_3: TWatchExpectationArray;
@ -54,6 +49,8 @@ type
function AddSimpleInt(AnExpr: string; AMtch: Int64; ATpNm: string): PWatchExpectation; function AddSimpleInt(AnExpr: string; AMtch: Int64; ATpNm: string): PWatchExpectation;
function AddSimpleUInt(AnExpr: string; AMtch: QWord; ATpNm: string): PWatchExpectation; function AddSimpleUInt(AnExpr: string; AMtch: QWord; ATpNm: string): PWatchExpectation;
procedure AdjustExpectToAddress(AWatchExp: PWatchExpectation);
procedure AddExpectSimple_1; procedure AddExpectSimple_1;
procedure AddExpectSimple_2; procedure AddExpectSimple_2;
procedure AddExpectSimple_3; procedure AddExpectSimple_3;
@ -109,10 +106,22 @@ begin
end; end;
{ TTestWatches } { TTestWatches }
procedure TTestWatches.AdjustExpectToAddress(AWatchExp: PWatchExpectation);
var
OtherWatchExp: PWatchExpectation;
s: String;
st: TSymbolType;
begin
OtherWatchExp := PWatchExpectation(AWatchExp^.UserData);
if OtherWatchExp = nil then exit;;
s := OtherWatchExp^.TheWatch.Values[1,0].Value;
delete(s, 1, pos('$', s) - 1); delete(s, pos(')', s), 99);
for st := low(TSymbolType) to high(TSymbolType) do
AWatchExp^.Result[st].ExpMatch := '\'+s;
end;
procedure TTestWatches.DoDbgOutput(Sender: TObject; const AText: String); procedure TTestWatches.DoDbgOutput(Sender: TObject; const AText: String);
begin begin
inherited DoDbgOutput(Sender, AText); inherited DoDbgOutput(Sender, AText);
@ -178,9 +187,11 @@ var
i: Integer; i: Integer;
s, s2, s2def: String; s, s2, s2def: String;
j: Integer; j: Integer;
r: PWatchExpectation;
begin begin
FCurrentExpect := @ExpectBreakSimple_1; FCurrentExpect := @ExpectBreakSimple_1;
{%region Int?Cardinal types}
for i := 0 to 3 do begin for i := 0 to 3 do begin
s2def := ''; s2def := '';
case i of case i of
@ -338,26 +349,34 @@ begin
AddSimpleInt(Format(s, ['SimpleField_Word1']), j+16, 'Word'); AddSimpleInt(Format(s, ['SimpleField_Word1']), j+16, 'Word');
AddSimpleInt(Format(s, ['SimpleField_DWord1']), j+17, 'LongWord'); AddSimpleInt(Format(s, ['SimpleField_DWord1']), j+17, 'LongWord');
AddSimpleInt(Format(s, ['SimpleField_QWord1']), j+18, 'QWord'); AddSimpleInt(Format(s, ['SimpleField_QWord1']), j+18, 'QWord');
//AddSimpleInt(Format(s, ['SimpleField_Single1']), 15, 'Byte');
//AddSimpleInt(Format(s, ['SimpleField_Double1']), 15, 'Byte');
//AddSimpleInt(Format(s, ['SimpleField_Ext1']), 15, 'Byte');
end; end;
{%region}
s := '%s';
AddFmtDef(Format(s, ['SimpleGlob_Single1']), '^99\.(2|19)', skSimple, '', [fTpMtch]);
AddFmtDef(Format(s, ['SimpleGlob_Double1']), '^199\.(3|29)', skSimple, '', [fTpMtch]);
AddFmtDef(Format(s, ['SimpleGlob_Ext1']), '^299\.(4|39)', skSimple, '', [fTpMtch]);
AddSimpleInt(Format(s, ['SimpleGlob_Comp1']), -2, '');
{%region AddressOf / Var param, hidden pointer} {%region AddressOf / Var param, hidden pointer}
//SimplePArg_Int1, SimplePVArg_Int1, SimplePLocal_Int1, SimplePGlob_Int1: PLongInt; //SimplePArg_Int1, SimplePVArg_Int1, SimplePLocal_Int1, SimplePGlob_Int1: PLongInt;
FSimplePArg_Int1 := AddFmtDef('SimplePArg_Int1', '\$[0-9A-F]', skPointer, ''); r := AddFmtDef('@SimpleArg_Int1', 'replaceme', skPointer, '');
FAddrSimpleArg_Int1 := AddFmtDef('@SimpleArg_Int1', 'replaceme', skPointer, ''); r^.OnBeforeTest := @AdjustExpectToAddress;
r^.UserData := AddFmtDef('SimplePArg_Int1', '\$[0-9A-F]', skPointer, '');
FSimplePVArg_Int1 := AddFmtDef('SimplePVArg_Int1', '\$[0-9A-F]', skPointer, ''); r := AddFmtDef('@SimpleVArg_Int1', 'replaceme', skPointer, '');
FAddrSimpleVArg_Int1 := AddFmtDef('@SimpleVArg_Int1', 'replaceme', skPointer, ''); r^.OnBeforeTest := @AdjustExpectToAddress;
UpdResMinFpc(FAddrSimpleVArg_Int1, stSymAll, 020600); r^.UserData := AddFmtDef('SimplePVArg_Int1', '\$[0-9A-F]', skPointer, '');
UpdResMinFpc(r, stSymAll, 020600);
FSimplePLocal_Int1 := AddFmtDef('SimplePLocal_Int1', '\$[0-9A-F]', skPointer, ''); r := AddFmtDef('@SimpleLocal_Int1', 'replaceme', skPointer, '');
FAddrSimpleLocal_Int1 := AddFmtDef('@SimpleLocal_Int1', 'replaceme', skPointer, ''); r^.OnBeforeTest := @AdjustExpectToAddress;
r^.UserData := AddFmtDef('SimplePLocal_Int1', '\$[0-9A-F]', skPointer, '');
r := AddFmtDef('@SimpleGlob_Int1', 'replaceme', skPointer, '');
r^.OnBeforeTest := @AdjustExpectToAddress;
r^.UserData := AddFmtDef('SimplePGlob_Int1', '\$[0-9A-F]', skPointer, '');
FSimplePGlob_Int1 := AddFmtDef('SimplePGlob_Int1', '\$[0-9A-F]', skPointer, '');
FAddrSimpleGlob_Int1 := AddFmtDef('@SimpleGlob_Int1', 'replaceme', skPointer, '');
{%region} {%region}
end; end;
@ -437,6 +456,7 @@ begin
AddSimpleInt('ArrayGlob_DynInt1[0]', 5511, M_Int); AddSimpleInt('ArrayGlob_DynInt1[0]', 5511, M_Int);
AddSimpleInt('ArrayGlob_DynInt1[19]', 5500, M_Int); AddSimpleInt('ArrayGlob_DynInt1[19]', 5500, M_Int);
AddFmtDef('ArrayGlob_StatInt1', '^[\(L].*6600, 6601, 6602', AddFmtDef('ArrayGlob_StatInt1', '^[\(L].*6600, 6601, 6602',
skArray, '', [fTpMtch]); skArray, '', [fTpMtch]);
AddSimpleInt('ArrayGlob_StatInt1[4]', 6600, M_Int); AddSimpleInt('ArrayGlob_StatInt1[4]', 6600, M_Int);
@ -445,27 +465,43 @@ begin
AddFmtDef('ArrayGlob_StatInt1[10]', '', skSimple, M_Int, [fTpMtch]); // Just do not crash AddFmtDef('ArrayGlob_StatInt1[10]', '', skSimple, M_Int, [fTpMtch]); // Just do not crash
AddFmtDef('ArrayGlob_StatInt1[-1]', '', skSimple, M_Int, [fTpMtch]); // Just do not crash AddFmtDef('ArrayGlob_StatInt1[-1]', '', skSimple, M_Int, [fTpMtch]); // Just do not crash
AddFmtDef('ArrayGlob_StatInt2', '^[\(L].*3300, 3301, 3302', AddFmtDef('ArrayGlob_StatInt2', '^[\(L].*3300, 3301, 3302',
skArray, '', [fTpMtch]); skArray, '', [fTpMtch]);
AddSimpleInt('ArrayGlob_StatInt2[-4]', 3300, M_Int); AddSimpleInt('ArrayGlob_StatInt2[-4]', 3300, M_Int);
AddSimpleInt('ArrayGlob_StatInt2[0]', 3304, M_Int); AddSimpleInt('ArrayGlob_StatInt2[0]', 3304, M_Int);
// EMPTY dyn array = nil AddFmtDef('FieldDynInt1', '^[\(L].*100, 101, 102', skArray, '', [fTpMtch]);
AddFmtDef('FieldDynClass1', '^[\(L].*?'+
'\(.*FIELDINT1 = 98700;.*FIELDINT2 = 98701;.*FIELDDYNAINT1 = \(9900, 9901\);.*\), ' +
'\(.*FIELDINT1 = 88700;.*FIELDINT2 = 88701;.*FIELDDYNAINT1 = \(8900, 8901\);.*\), ' +
'\(.*FIELDINT1 = 78700;.*FIELDINT2 = 78701;.*FIELDDYNAINT1 = \(7900, 7901, 7902\);.*\)',
skArray, '', [fTpMtch]);
end; end;
procedure TTestWatches.RunTestWatches(NamePreFix: String; TestExeName, ExtraOpts: String; procedure TTestWatches.RunTestWatches(NamePreFix: String; TestExeName, ExtraOpts: String;
UsedUnits: array of TUsesDir); UsedUnits: array of TUsesDir);
var var
dbg: TGDBMIDebugger; dbg: TGDBMIDebugger;
Only: Integer; Only: Integer;
OnlyName, OnlyNamePart: String; OnlyName, OnlyNamePart: String;
procedure SetBreak(AFileName: String; ALineNum: Integer);
begin
with dbg.BreakPoints.Add(AFileName, ALineNum) do begin
InitialEnabled := True;
Enabled := True;
end;
end;
var var
i: Integer; i: Integer;
WListSimple1, WListSimple2, WListSimple3,
WListArray1: TTestWatchArray;
st: TSymbolType; st: TSymbolType;
s: String; s: String;
@ -497,30 +533,18 @@ begin
dbg := StartGDB(AppDir, TestExeName); dbg := StartGDB(AppDir, TestExeName);
FWatches := Watches.Watches; FWatches := Watches.Watches;
with dbg.BreakPoints.Add('TestWatchesUnitSimple.pas', BREAK_LINE_TestWatchesUnitSimple_1) do begin SetBreak('TestWatchesUnitSimple.pas', BREAK_LINE_TestWatchesUnitSimple_1);
InitialEnabled := True; SetBreak('TestWatchesUnitSimple.pas', BREAK_LINE_TestWatchesUnitSimple_2);
Enabled := True; SetBreak('TestWatchesUnitSimple.pas', BREAK_LINE_TestWatchesUnitSimple_3);
end; SetBreak('TestWatchesUnitArray.pas', BREAK_LINE_TestWatchesUnitArray);
with dbg.BreakPoints.Add('TestWatchesUnitSimple.pas', BREAK_LINE_TestWatchesUnitSimple_2) do begin
InitialEnabled := True;
Enabled := True;
end;
with dbg.BreakPoints.Add('TestWatchesUnitSimple.pas', BREAK_LINE_TestWatchesUnitSimple_3) do begin
InitialEnabled := True;
Enabled := True;
end;
with dbg.BreakPoints.Add('TestWatchesUnitArray.pas', BREAK_LINE_TestWatchesUnitArray) do begin
InitialEnabled := True;
Enabled := True;
end;
if dbg.State = dsError then if dbg.State = dsError then
Fail(' Failed Init'); Fail(' Failed Init');
AddWatches(ExpectBreakSimple_1, WListSimple1, FWatches, Only, OnlyName, OnlyNamePart); AddWatches(ExpectBreakSimple_1, FWatches, Only, OnlyName, OnlyNamePart);
AddWatches(ExpectBreakSimple_2, WListSimple2, FWatches, Only, OnlyName, OnlyNamePart); AddWatches(ExpectBreakSimple_2, FWatches, Only, OnlyName, OnlyNamePart);
AddWatches(ExpectBreakSimple_3, WListSimple3, FWatches, Only, OnlyName, OnlyNamePart); AddWatches(ExpectBreakSimple_3, FWatches, Only, OnlyName, OnlyNamePart);
AddWatches(ExpectBreakArray_1, WListArray1, FWatches, Only, OnlyName, OnlyNamePart); AddWatches(ExpectBreakArray_1, FWatches, Only, OnlyName, OnlyNamePart);
(* Start debugging *) (* Start debugging *)
dbg.ShowConsole := True; dbg.ShowConsole := True;
@ -531,45 +555,25 @@ begin
TestTrue('Hit BREAK_LINE_TestWatchesUnitSimple_1', False); TestTrue('Hit BREAK_LINE_TestWatchesUnitSimple_1', False);
exit; exit;
end; end;
(* Hit first breakpoint: *) (* Hit first breakpoint: *)
for st := low(TSymbolType) to high(TSymbolType) do begin TestWatchList('Simple1',ExpectBreakSimple_1, dbg, Only, OnlyName, OnlyNamePart);
s := FSimplePArg_Int1^.TheWatch.Values[1,0].Value;
delete(s, 1, pos('$', s) - 1); delete(s, pos(')', s), 99);
FAddrSimpleArg_Int1^.Result[st].ExpMatch := '\'+s;
s := FSimplePVArg_Int1^.TheWatch.Values[1,0].Value;
delete(s, 1, pos('$', s) - 1); delete(s, pos(')', s), 99);
FAddrSimpleVArg_Int1^.Result[st].ExpMatch := '\'+s;
s := FSimplePGlob_Int1^.TheWatch.Values[1,0].Value;
delete(s, 1, pos('$', s) - 1); delete(s, pos(')', s), 99);
FAddrSimpleGlob_Int1^.Result[st].ExpMatch := '\'+s;
s := FSimplePLocal_Int1^.TheWatch.Values[1,0].Value;
delete(s, 1, pos('$', s) - 1); delete(s, pos(')', s), 99);
FAddrSimpleLocal_Int1^.Result[st].ExpMatch := '\'+s;
end;
TestWatchList('Simple1',ExpectBreakSimple_1, WListSimple1, dbg, Only, OnlyName, OnlyNamePart);
dbg.Run; dbg.Run;
if not TestTrue('State=Pause', dbg.State = dsPause) then begin if not TestTrue('State=Pause', dbg.State = dsPause) then begin
TestTrue('Hit BREAK_LINE_TestWatchesUnitSimple', False); TestTrue('Hit BREAK_LINE_TestWatchesUnitSimple', False);
exit; exit;
end; end;
(* Hit 2nd Simple breakpoint: *) (* Hit 2nd Simple breakpoint: *)
TestWatchList('Simple2',ExpectBreakSimple_2, WListSimple2, dbg, Only, OnlyName, OnlyNamePart); TestWatchList('Simple2',ExpectBreakSimple_2, dbg, Only, OnlyName, OnlyNamePart);
dbg.Run; dbg.Run;
if not TestTrue('State=Pause', dbg.State = dsPause) then begin if not TestTrue('State=Pause', dbg.State = dsPause) then begin
TestTrue('Hit BREAK_LINE_TestWatchesUnitSimple', False); TestTrue('Hit BREAK_LINE_TestWatchesUnitSimple', False);
exit; exit;
end; end;
(* Hit 3rd Simlpe breakpoint: *) (* Hit 3rd Simlpe breakpoint: *)
TestWatchList('Simple3',ExpectBreakSimple_3, WListSimple3, dbg, Only, OnlyName, OnlyNamePart); TestWatchList('Simple3',ExpectBreakSimple_3, dbg, Only, OnlyName, OnlyNamePart);
// array // array
@ -582,7 +586,7 @@ begin
end; end;
(* Hit 11st Array breakpoint: *) (* Hit 11st Array breakpoint: *)
TestWatchList('Array1',ExpectBreakArray_1, WListArray1, dbg, Only, OnlyName, OnlyNamePart); TestWatchList('Array1',ExpectBreakArray_1, dbg, Only, OnlyName, OnlyNamePart);
dbg.Run; dbg.Run;

View File

@ -94,7 +94,7 @@ begin
{$ENDIF} {$ENDIF}
FpcBuild.ShowWindow := swoHIDE; FpcBuild.ShowWindow := swoHIDE;
CmdLine := FpcExe + ' -MObjFPC -FUlib -o'+ ExeName + ' ' + FpcOpts + ' ' + PrgName; CmdLine := FpcExe + ' -B -MObjFPC -FUlib -o'+ ExeName + ' ' + FpcOpts + ' ' + PrgName;
debugln(['**** running compiler: ', CmdLine]); debugln(['**** running compiler: ', CmdLine]);
FpcBuild.CommandLine := CmdLine; FpcBuild.CommandLine := CmdLine;
FCommandLine := CmdLine; FCommandLine := CmdLine;

View File

@ -85,6 +85,8 @@ const
WatchExpFlagSIgnTpName = [IgnStabs, IgnDwrf, IgnDwrf2, IgnDwrf2IfNoSet, IgnDwrf3, IgnTpName, IgnTpNameDw, IgnTpNameDw2, IgnTpNameDw3, IgnTpNameSt]; WatchExpFlagSIgnTpName = [IgnStabs, IgnDwrf, IgnDwrf2, IgnDwrf2IfNoSet, IgnDwrf3, IgnTpName, IgnTpNameDw, IgnTpNameDw2, IgnTpNameDw3, IgnTpNameSt];
type type
PWatchExpectation= ^TWatchExpectation;
TWatchExpectOnBeforeTest = procedure(AWatchExp: PWatchExpectation) of object;
TFullTypeMemberExpectationResult = record TFullTypeMemberExpectationResult = record
Name: string; Name: string;
@ -94,7 +96,6 @@ type
end; end;
TFullTypeMemberExpectationResultArray = array of TFullTypeMemberExpectationResult; TFullTypeMemberExpectationResultArray = array of TFullTypeMemberExpectationResult;
PWatchExpectation= ^TWatchExpectation;
TWatchExpectationResult = record TWatchExpectationResult = record
ExpMatch: string; ExpMatch: string;
ExpKind: TDBGSymbolKind; ExpKind: TDBGSymbolKind;
@ -111,22 +112,23 @@ type
EvaluateFlags: TDBGEvaluateFlags; EvaluateFlags: TDBGEvaluateFlags;
StackFrame: Integer; StackFrame: Integer;
Result: Array [TSymbolType] of TWatchExpectationResult; Result: Array [TSymbolType] of TWatchExpectationResult;
TheWatch: TTestWatch; TheWatch: TTestWatch;
UserData: Pointer;
OnBeforeTest: TWatchExpectOnBeforeTest;
end; end;
TWatchExpectationArray = array of TWatchExpectation; TWatchExpectationArray = array of TWatchExpectation;
TTestWatchArray = Array of TTestWatch;
{ TTestWatchesBase } { TTestWatchesBase }
TTestWatchesBase = class(TGDBTestCase) TTestWatchesBase = class(TGDBTestCase)
protected protected
procedure TestWatch(Name: String; ADbg: TDebuggerIntf; procedure TestWatch(Name: String; ADbg: TDebuggerIntf;
AWatch: TTestWatch; Data: TWatchExpectation; WatchValue: String = ''); AWatch: TTestWatch; Data: TWatchExpectation; WatchValue: String = '');
procedure AddWatches(ExpectList: TWatchExpectationArray; var WatchList: TTestWatchArray; procedure AddWatches(ExpectList: TWatchExpectationArray;
AWatches: TWatches; AWatches: TWatches;
Only: Integer; OnlyName, OnlyNamePart: String); Only: Integer; OnlyName, OnlyNamePart: String);
procedure TestWatchList(AName: String; ExpectList: TWatchExpectationArray; WatchList: TTestWatchArray; procedure TestWatchList(AName: String; ExpectList: TWatchExpectationArray;
ADbg: TDebuggerIntf; ADbg: TDebuggerIntf;
Only: Integer; OnlyName, OnlyNamePart: String); Only: Integer; OnlyName, OnlyNamePart: String);
end; end;
@ -398,6 +400,8 @@ var
begin begin
if not TestTrue('Dbg did NOT enter dsError', ADbg.State <> dsError) then exit; if not TestTrue('Dbg did NOT enter dsError', ADbg.State <> dsError) then exit;
if Data.OnBeforeTest <> nil then Data.OnBeforeTest(@Data);
rx := nil; rx := nil;
Stack := Data.StackFrame; Stack := Data.StackFrame;
DataRes := Data.Result[SymbolType]; DataRes := Data.Result[SymbolType];
@ -513,9 +517,8 @@ begin
end; end;
procedure TTestWatchesBase.AddWatches(ExpectList: TWatchExpectationArray; procedure TTestWatchesBase.AddWatches(ExpectList: TWatchExpectationArray; AWatches: TWatches;
var WatchList: TTestWatchArray; AWatches: TWatches; Only: Integer; OnlyName, Only: Integer; OnlyName, OnlyNamePart: String);
OnlyNamePart: String);
function SkipTest(const Data: TWatchExpectation): Boolean; function SkipTest(const Data: TWatchExpectation): Boolean;
begin begin
@ -535,22 +538,20 @@ procedure TTestWatchesBase.AddWatches(ExpectList: TWatchExpectationArray;
var var
i: Integer; i: Integer;
begin begin
SetLength(WatchList, length(ExpectList));
for i := low(ExpectList) to high(ExpectList) do begin for i := low(ExpectList) to high(ExpectList) do begin
if not MatchOnly(ExpectList[i], i) then continue; if not MatchOnly(ExpectList[i], i) then continue;
if not SkipTest(ExpectList[i]) then begin if not SkipTest(ExpectList[i]) then begin
WatchList[i] := TTestWatch.Create(AWatches); ExpectList[i].TheWatch := TTestWatch.Create(AWatches);
WatchList[i].Expression := ExpectList[i].Expression; ExpectList[i].TheWatch.Expression := ExpectList[i].Expression;
WatchList[i].DisplayFormat := ExpectList[i].DspFormat; ExpectList[i].TheWatch.DisplayFormat := ExpectList[i].DspFormat;
WatchList[i].EvaluateFlags:= ExpectList[i].EvaluateFlags; ExpectList[i].TheWatch.EvaluateFlags:= ExpectList[i].EvaluateFlags;
WatchList[i].enabled := True; ExpectList[i].TheWatch.enabled := True;
ExpectList[i].TheWatch := WatchList[i];
end; end;
end; end;
end; end;
procedure TTestWatchesBase.TestWatchList(AName: String; ExpectList: TWatchExpectationArray; procedure TTestWatchesBase.TestWatchList(AName: String; ExpectList: TWatchExpectationArray;
WatchList: TTestWatchArray; ADbg: TDebuggerIntf; Only: Integer; OnlyName, ADbg: TDebuggerIntf; Only: Integer; OnlyName,
OnlyNamePart: String); OnlyNamePart: String);
function SkipTest(const Data: TWatchExpectation): Boolean; function SkipTest(const Data: TWatchExpectation): Boolean;
@ -574,7 +575,7 @@ begin
for i := low(ExpectList) to high(ExpectList) do begin for i := low(ExpectList) to high(ExpectList) do begin
if not MatchOnly(ExpectList[i], i) then continue; if not MatchOnly(ExpectList[i], i) then continue;
if not SkipTest(ExpectList[i]) then if not SkipTest(ExpectList[i]) then
TestWatch(AName + ' '+IntToStr(i)+' ', ADbg, WatchList[i], ExpectList[i]); TestWatch(AName + ' '+IntToStr(i)+' ', ADbg, ExpectList[i].TheWatch, ExpectList[i]);
end; end;
end; end;

View File

@ -1688,7 +1688,6 @@ var
var var
i: Integer; i: Integer;
WList, WListSub, WListArray: Array of TTestWatch;
begin begin
TestBaseName := NamePreFix; TestBaseName := NamePreFix;
@ -1735,9 +1734,9 @@ begin
Fail(' Failed Init'); Fail(' Failed Init');
(* Create all watches *) (* Create all watches *)
AddWatches(ExpectBreakFoo, WList, FWatches, Only, OnlyName, OnlyNamePart); AddWatches(ExpectBreakFoo, FWatches, Only, OnlyName, OnlyNamePart);
AddWatches(ExpectBreakSubFoo, WListSub, FWatches, Only, OnlyName, OnlyNamePart); AddWatches(ExpectBreakSubFoo, FWatches, Only, OnlyName, OnlyNamePart);
AddWatches(ExpectBreakFooArray, WListArray, FWatches, Only, OnlyName, OnlyNamePart); AddWatches(ExpectBreakFooArray, FWatches, Only, OnlyName, OnlyNamePart);
(* Start debugging *) (* Start debugging *)
dbg.ShowConsole := True; dbg.ShowConsole := True;
@ -1747,7 +1746,7 @@ begin
then begin then begin
(* Hit first breakpoint: BREAK_LINE_FOOFUNC_NEST SubFoo -- (1st loop) Called with none nil data *) (* Hit first breakpoint: BREAK_LINE_FOOFUNC_NEST SubFoo -- (1st loop) Called with none nil data *)
TestWatchList('Brk1', ExpectBreakSubFoo, WListSub, dbg, Only, OnlyName, OnlyNamePart); TestWatchList('Brk1', ExpectBreakSubFoo, dbg, Only, OnlyName, OnlyNamePart);
dbg.Run; dbg.Run;
end end
@ -1771,7 +1770,7 @@ begin
for i := low(ExpectBreakFoo) to high(ExpectBreakFoo) do begin for i := low(ExpectBreakFoo) to high(ExpectBreakFoo) do begin
if not MatchOnly(ExpectBreakFoo[i], i) then continue; if not MatchOnly(ExpectBreakFoo[i], i) then continue;
if not SkipTest(ExpectBreakFoo[i]) then if not SkipTest(ExpectBreakFoo[i]) then
TestWatch('Brk2 '+IntToStr(i)+' ', dbg, WList[i], ExpectBreakFoo[i]); TestWatch('Brk2 '+IntToStr(i)+' ', dbg, ExpectBreakFoo[i].TheWatch, ExpectBreakFoo[i]);
end; end;
dbg.Run; dbg.Run;
@ -1782,7 +1781,7 @@ begin
then begin then begin
(* Hit 2nd breakpoint: BREAK_LINE_FOOFUNC_ARRAY SubFoo_Watches -- (1st loop) Called with none nil data *) (* Hit 2nd breakpoint: BREAK_LINE_FOOFUNC_ARRAY SubFoo_Watches -- (1st loop) Called with none nil data *)
TestWatchList('Brk3', ExpectBreakFooArray, WListArray, dbg, Only, OnlyName, OnlyNamePart); TestWatchList('Brk3', ExpectBreakFooArray, dbg, Only, OnlyName, OnlyNamePart);
dbg.Run; dbg.Run;
end end