Skip to content

Commit 98c53a3

Browse files
committed
zero size structs with extern (C) attribute
1 parent 7a209db commit 98c53a3

File tree

1 file changed

+12
-7
lines changed

1 file changed

+12
-7
lines changed

spec/struct.dd

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,9 @@ $(H2 $(LNAME2 struct_layout, Struct Layout))
169169
the first field and the start of the object.
170170
)
171171

172-
$(P Structs with no fields of non-zero size (aka $(I Empty Structs)) have a size of one byte.)
172+
$(P A struct with no fields of non-zero size is an $(I Empty Struct).
173+
An Empty Struct with a $(DDSUBLINK spec/attribute, linkage, Linkage Attribute) of `extern (C)` has a size of zero.
174+
Otherwise, its size is one byte.)
173175

174176
$(P Non-static $(RELATIVE_LINK2 nested, function-nested D structs), which access the context of
175177
their enclosing scope, have an extra field.
@@ -179,20 +181,22 @@ $(H2 $(LNAME2 struct_layout, Struct Layout))
179181
$(OL
180182
$(LI The default layout of the fields of a struct is an exact
181183
match with the $(I associated C compiler).)
182-
$(LI g++ and clang++ differ in how empty structs are handled. Both return `1` from `sizeof`,
184+
$(LI g++ and clang++ differ in how Empty Structs are handled. Both return `1` from `sizeof`,
183185
however, clang++ does not push them onto the parameter stack while g++ does. This is a
184186
binary incompatibility between g++ and clang++.
185187
dmd follows clang++ behavior for OSX and FreeBSD, and g++ behavior for Linux and other
186188
Posix platforms.
187189
)
188-
$(LI clang and gcc both return `0` from `sizeof` for empty structs. Using `extern "C++"`
189-
in clang++ and g++ does not cause them to conform to the behavior of their respective C compilers.)
190+
$(LI C compilers normally evaluate `sizeof` applied to Empty Structs as `0`, although it
191+
is undefined behavior according to the C11 Standard.
192+
C++ compilers normally evaluate the size as `1`, even if `extern "C"` is applied.
193+
)
190194
))
191195

192196
$(UNDEFINED_BEHAVIOR
193197
$(OL
194198
$(LI The padding data can be accessed, but its contents are undefined.)
195-
$(LI Do not pass or return structs with no fields of non-zero size to `extern (C)` functions.
199+
$(LI Do not pass or return Empty Structs to `extern (C)` functions.
196200
According to C11 6.7.2.1p8 this is undefined behavior.)
197201
))
198202

@@ -202,8 +206,9 @@ $(H2 $(LNAME2 struct_layout, Struct Layout))
202206
attributes to describe an exact match. Using a $(DDSUBLINK spec/version, static-assert, Static Assert)
203207
to ensure the result is as expected.)
204208
$(LI Although the contents of the padding are often zero, do not rely on that.)
205-
$(LI Avoid using empty structs when interfacing with C and C++ code.)
206-
$(LI Avoid using empty structs as parameters or arguments to variadic functions.)
209+
$(LI Avoid using Empty Structs when interfacing with C++ code that declares them with `extern "C"`.
210+
Add a one byte dummy field to those structs.)
211+
$(LI Avoid using Empty Structs as parameters or arguments to variadic functions.)
207212
))
208213

209214
$(H2 $(LNAME2 POD, Plain Old Data))

0 commit comments

Comments
 (0)