FR: allow nested fields for that offsetof-like trick that I almost sure already special-cased.
`PtrUint(@PRec(nil)^.field)` is the way to get the offset of the `field` in the `Rec` that is even used by the compiler codebase. The most notable thing I found about it is that it becomes **true constant**. (So is it special-cased? Cool.) However, it works worse for nested fields. The expression `PtrUint(@PType(nil)^.container.field)` can still be used in the procedure body, but does not become true constant, as can be observed in the example below on how it fails to compile explicit **const** declaration and on worse code generated for `MyObjFromB_SubOffsetOf`. ```pascal type PBContainer = ^BContainer; BContainer = record b: int32; end; PMyObj = ^MyObj; MyObj = record dummy: int32; a: int32; bCtr: BContainer; end; const AOfs = PtrUint(@PMyObj(nil)^.a); // BOfs = PtrUint(@PMyObj(nil)^.bCtr.b); // does not compile BOfs = PtrUint(@PMyObj(nil)^.bCtr) + PtrUint(@PBContainer(nil)^.b); // ugly workaround function MyObjFromA_SubOffsetOf(aPtr: PInt32): PMyObj; begin result := pointer(aPtr) - PtrUint(@PMyObj(nil)^.a); end; function MyObjFromA_SubConst(aPtr: PInt32): PMyObj; begin result := pointer(aPtr) - AOfs; end; function MyObjFromB_SubOffsetOf(bPtr: PInt32): PMyObj; begin result := pointer(bPtr) - PtrUint(@PMyObj(nil)^.bCtr.b); end; function MyObjFromB_SubConst(bPtr: PInt32): PMyObj; begin result := pointer(bPtr) - BOfs; end; var mo: MyObj; begin writeln('''a'' offset in ''MyObj'': ', AOfs); writeln('''b'' offset in ''MyObj'': ', BOfs); writeln('@mo: ', HexStr(@mo)); writeln('@mo recovered from @mo.a by subtracting "offsetof": ', HexStr(MyObjFromA_SubOffsetOf(@mo.a))); writeln('@mo recovered from @mo.a by subtracting constant: ', HexStr(MyObjFromA_SubConst(@mo.a))); writeln('@mo recovered from @mo.b by subtracting "offsetof": ', HexStr(MyObjFromB_SubOffsetOf(@mo.bCtr.b))); writeln('@mo recovered from @mo.b by subtracting constant: ', HexStr(MyObjFromB_SubConst(@mo.bCtr.b))); end. ``` ``` 'a' offset in 'MyObj': 4 'b' offset in 'MyObj': 8 @mo: 0000000100012010 @mo recovered from @mo.a by subtracting "offsetof": 0000000100012010 @mo recovered from @mo.a by subtracting constant: 0000000100012010 @mo recovered from @mo.b by subtracting "offsetof": 0000000100012010 @mo recovered from @mo.b by subtracting constant: 0000000100012010 ``` `MyObjFromA_SubOffsetOf`: ```nasm lea rax,[rcx-$04] ret ``` `MyObjFromA_SubConst`: ```nasm lea rax,[rcx-$04] ret ``` `MyObjFromB_SubOffsetOf`: ```nasm mov rax,rcx mov edx,$00000008 sub rax,rdx ret ``` `MyObjFromB_SubConst`: ```nasm lea rax,[rcx-$08] ret ```
issue