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
TMyBar
is 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
TMyBar
it 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 `TGenFoo1
crc713F463B.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.