Missing dwarf info for nested classes (in generics) - too eager to strip info, assuming it is not used
- FPC 3.3.1 from 27th Jun 2022
- Windows 10
- 64 bit
In some cases, FPC omits dwarf info for some classes. I have only been able to reproduce this with generics, but as far as I can see that may just be a way to expose the underlaying issue, which is that FPC does not realize the class is being used.
In the code below (and attached) no info is generated for TMyBar.
FPC 3.2.3 generates info for the VMT (but also not for the actual class)
<1><e3eed>: Abbrev Number: 2 (DW_TAG_typedef)
<e3eee> DW_AT_name : $vmtdef$TGenFoo$1$crc9F312717.TMYBAR
<e3f13> DW_AT_type : <0xe3f17>
<1><e3f17>: Abbrev Number: 9 (DW_TAG_structure_type)
<e3f18> DW_AT_name : $VMTDEF$TGENFOO$1$CRC9F312717.TMYBAR
<e3f3d> DW_AT_byte_size : 216
FPC 3.3.1 generates nothing.
However having a class (for typecasting in the debugger) would really be useful.
If a public field FBarData:TMyBar; is added in TGenFoo then FPC notes that the class is used, and generates info.
However, this info is not useful:
- if you have several specializations of
TGenFoo - Then for each of them a dwarf entry
TMyBaris created- all with the same name
- all as stand-alone type, the type is not recognizable as being a subtype of the specialization of
TGenFoo.
Well...
- The type is refereed by the field
FBarData, so if inspecting the specializedTGenFoo, the type will be found. - But if attempting to typecast a variable of that class, it can't be told which
TMyBarit should be. Besides the ClassName of such a variable is something like:TGENFOO$1$CRC9F312717.TMYBAR
So, IMHO, it would be better if the dwarf entry for that class was also named TGENFOO$1$CRC9F312717.TMYBAR
Never mind, that FpDebug still needs to learn to typecast to `TGenFoo1crc713F463B.TMyBar`
Especially, given that this is one single name (One single name in the dwarf info table), and the dot normally separates names...
program project1;
{$mode objfpc}{$H+}
uses Unit1;
var
f: TFoo;
b: TBar;
begin
f := TMyFoo.Create;
b := f.GetBar;
b.GetData;
end.
unit Unit1;
{$mode ObjFPC}{$H+}
interface
type
TBar = class
public
function GetData: Integer; virtual; abstract;
end;
TFoo = class
function GetBar: TBar; virtual;
end;
generic TGenFoo<T> = class(TFoo)
private type
TMyBar = class(TBar)
public
FData: T;
function GetData: Integer; override;
end;
public
// FBarData:TMyBar;
function GetBar: TBar; override;
end;
TMyFoo = class(specialize TGenFoo<integer>)
end;
implementation
function TGenFoo.TMyBar.GetData: Integer;
begin
Result := FData;
end;
function TGenFoo.GetBar: TBar;
begin
Result := TMyBar.Create;
end;
function TFoo.GetBar: TBar;
begin
Result := nil;
end;
end.