You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have two helper functions in C to aid inspection (lldb seems to sometimes have trouble recognizing Swift pointer variables):
// Just `printf("%p\n", p);`voidwhats_this_addr(void*p);
// Wrapper around memcpy, allowing inspection of the addresses// and/or memory in the debuggervoidmy_memcpy(void*dest, constvoid*src, size_tlen);
Then, working with a heap-allocated instance of the struct in Swift:
typealiasFooRef=UnsafeMutablePointer<Foo>letnew:FooRef=...// Allocate via `UnsafeMutableRawPointer` and then `bindMemory`letpayloadStart=UnsafeMutableRawPointer(&new.pointee.payload)whats_this_addr(payloadStart)// Garbage value, consistently somewhere above `new`// Curiouserletpayload:[Int8]=...
_ = payload.withUnsafeBytes{my_memcpy(payloadStart, $0.baseAddress!, payload.count)// In a debug build, the first arg is 0x7ff... inside my_memcpy}// And curiouserwhats_this_addr(&new.pointee.payload)// Garbage, _different_ from whats_this_addr(payloadStart) above -- consistently somewhere below `new`whats_this_addr(&new.pointee.payload)// NULLwhats_this_addr(payloadStart)// NULL?!
If the offset/pointer is calculated in C, Swift can use it perfectly well. The problem seems to be solely with Swift's calculation of the location of the field.
The address range is different in a release build (tested with -fno-pie), but the behavior is effectively the same.
*In lieu of a true flexible array member int8_t payload[], which isn't imported at all. (Swift does handle a member with declared length 1 correctly, however.)
The text was updated successfully, but these errors were encountered:
The problem is deeper than that. The Clang Importer imports constant-sized arrays by mapping them directly to a TupleType with matching cardinality. So, a VLA is actually being imported as (), which has no size under our ABI. And, since we lack the global rule C and C++ have about always being to take the address of a field we have no formal reason to reserve space for it.
Now, is this a bug is the question. Zero-sized arrays like this for trailing storage are a GNU C extension, and we have not historically gone out of our way to support these kinds of language extensions. This feels like a point to raise on the Swift forums.
since we lack the global rule C and C++ have about always being to take the address of a field
Ah, even when the layout is defined in C? Is that deliberate or "not implemented yet"?
a GNU C extension
Right, understood. I ran into this because I actually wanted a flexible array member int8_t payload[]; which, as noted, is not imported at all. I figured this was worth filing given that the length-1 version will work as expected.
Since flexible array members are part of the C standard, I suppose that's the real question I should post about – i.e., how can Swift support them?
Attachment: Download
Environment
Apple Swift version 5.1.3 (swiftlang-1100.0.282.1 clang-1100.0.33.15)
Target: x86_64-apple-darwin18.6.0
Additional Detail from JIRA
md5: 99c1361955b620d095fc55793eaa91e4
Issue Description:
Given a C struct with a trailing member that is a 0-length array*:
Swift cannot produce a valid pointer to the
payload
field.Note first,
I have two helper functions in C to aid inspection (lldb seems to sometimes have trouble recognizing Swift pointer variables):
Then, working with a heap-allocated instance of the struct in Swift:
If the offset/pointer is calculated in C, Swift can use it perfectly well. The problem seems to be solely with Swift's calculation of the location of the field.
The address range is different in a release build (tested with
-fno-pie
), but the behavior is effectively the same.Full running example attached, also available at https://github.com/woolsweater/flex-arr-mem , "bug-report" branch (there is a fuller example on master).
—
*In lieu of a true flexible array member
int8_t payload[]
, which isn't imported at all. (Swift does handle a member with declared length 1 correctly, however.)The text was updated successfully, but these errors were encountered: