diff --git a/spec/abi.dd b/spec/abi.dd index 32a00ce71c..4562a043ca 100644 --- a/spec/abi.dd +++ b/spec/abi.dd @@ -68,9 +68,14 @@ $(H2 $(LNAME2 delegates, Delegates)) function's stack frame (nested functions). ) -$(H2 $(LNAME2 structs, Structs)) +$(H2 $(LNAME2 structs, Structs and Unions)) - $(P Conforms to the target's C ABI struct layout.) + $(P These conform to the target's C ABI struct layout, except:) + + * An `extern(D)` struct or union with no fields has size 1, not 0. + See $(DDSUBLINK spec/struct, struct_layout, Struct Layout). + * Unions are $(RELATIVE_LINK2 name_mangling, name-mangled) as if they were structs. + * The rest of this document treats unions extrinsically the same as structs. $(H2 $(LNAME2 classes, Classes)) diff --git a/spec/struct.dd b/spec/struct.dd index c0dcf5c176..efdabc0c5c 100644 --- a/spec/struct.dd +++ b/spec/struct.dd @@ -176,7 +176,18 @@ $(H2 $(LNAME2 struct_layout, Struct Layout)) the first field and the start of the object. ) - $(P Structs with no fields of non-zero size (aka $(I Empty Structs)) have a size of one byte.) + $(P $(DDSUBLINK spec/attribute, linkage, `extern(D)`) structs with no fields of non-zero + size (aka $(I Empty Structs)) have a size of one byte.) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + extern(C) struct C {} + struct D {} + + static assert(C.sizeof == 0); + static assert(D.sizeof == 1); + --- + ) $(P Non-static $(RELATIVE_LINK2 nested, function-nested D structs), which access the context of their enclosing scope, have an extra field.