Bug 20564 – Member function increases struct size when the struct is defined in a function

Status
RESOLVED
Resolution
DUPLICATE
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2020-02-07T11:57:45Z
Last change time
2020-03-21T03:56:41Z
Assigned to
No Owner
Creator
Ferdinand Majerech

Comments

Comment #0 by kiithsacmp — 2020-02-07T11:57:45Z
Adding a method to a struct definition in a function increases the struct size. Build this code to reproduce: ``` void fun() { struct InnerFun { ubyte a; void fun() {} } struct InnerNoFun { ubyte a; } // prints 16, expected 1 pragma(msg, "InnerFun ", InnerFun.sizeof); // prints 1 pragma(msg, "InnerNoFun ", InnerNoFun.sizeof); } struct OuterFun { ubyte a; void fun() {} } struct OuterNoFun { ubyte a; } // prints 1 pragma(msg, "OuterFun ", OuterFun.sizeof); // prints 1 pragma(msg, "OuterNoFun ", OuterNoFun.sizeof); void main(){} ``` Actual results: ``` OuterFun 1LU OuterNoFun 1LU InnerFun 16LU InnerNoFun 1LU ``` Expected results: ``` OuterFun 1LU OuterNoFun 1LU InnerFun 1LU InnerNoFun 1LU ``` Reproduced on DMD 2.090, DMD 2.086, LDC 1.8.0 (based on DMD 2.078.3) on Ubuntu 18.04 Discovered while trying out `std.bitmanip.bitfields!()` in a unittest, where generated methods broke the test.
Comment #1 by simen.kjaras — 2020-02-07T12:29:03Z
This is mostly expected. When a nested struct has a method, that method has access to the context of the function in which it is defined, so you can do things like this: void fun() { int i = 0; struct S { void gun() { ++i; } } S s; s.gun(); assert(i == 1); } Since the nested struct may be passed to other functions or even returned from the function that created it, this context pointer needs to be embedded in the struct, which explains the size increase - 1 byte for the explicit field, a context pointer of 8 bytes, and 7 bytes of padding to make sure the pointer is aligned. Regardless, in your case the context pointer is strictly unnecessary, and could be elided. That makes this issue a duplicate of issue 10276. *** This issue has been marked as a duplicate of issue 10276 ***
Comment #2 by b2.temp — 2020-02-07T19:22:07Z
set the inner struct static when the context pointer is not required void fun() { static struct InnerFun { ubyte a; void fun() {} } static struct InnerNoFun { ubyte a; } } both have size 1 now.