Bug 19667 – .offsetof cannot be used on non-public members of aggregates in different modules
Status
RESOLVED
Resolution
INVALID
Severity
normal
Priority
P3
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2019-02-11T04:43:10Z
Last change time
2023-07-27T18:51:51Z
Assigned to
No Owner
Creator
Adam Wilson
Comments
Comment #0 by flyboynw — 2019-02-11T04:43:10Z
Consider the following code:
module mod1;
public struct S {
public int publicField;
private int privateField;
}
-----
module mod2;
import mod1;
void main() {
import std.conv : to;
import std.stdio : writeln;
writeln(to!string(S.publicField.offsetof)); //OK
writeln(to!string(S.privateField.offsetof)); //Compiler error
}
This means that is impossible to correctly map the memory layout a given aggregate from outside of the implementing module using only .offsetof.
I am aware that .tupleof can be used to bypass the protection checks, but using .tupleof is a hack. Why can .tupleof bypass the checks, but not .offsetof?
Comment #1 by sprink.noreply — 2019-02-18T23:23:58Z
tupleof is effective a member function of S that has access to those private fields. The returned type is a new tuple, not of type S so none of the fields are private. If you want to know the offset of you can do the same thing.
struct S {
public int publicField;
private int privateField;
public auto tupleof() {
return Tuple!("publicField", publicField, "privateField", privateField);
}
public auto privateFieldOffsetOf() { return privateField.offsetof; }
}
Comment #2 by dkorpel — 2023-07-27T18:51:51Z
Access checks can be circumvented with __traits(getMember) and tupleof for meta-programming purposes. `S.privateField` fails the access check before `.offsetof` is queried on that. Making `.offsetof` undo the access check of its operand is more hacky than using existing methods.