mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 13:10:12 +03:00
Fix bugzilla 24592 - ImportC: Bitfield layout wrong for int64 on 32-bit Linux
Type ulong is 64-bit on 32-bit Linux, but has 32-bit alignment. This affects the layout of bitfields. Also add a new test for ImportC bitfields, which compares size, alignment and layout with the host C++ compiler. The existing tests compared with fixed values instead.
This commit is contained in:
parent
86b71a29ed
commit
4c82050e94
7 changed files with 257 additions and 6 deletions
90
compiler/test/runnable_cxx/testbitfields.d
Normal file
90
compiler/test/runnable_cxx/testbitfields.d
Normal file
|
@ -0,0 +1,90 @@
|
|||
// EXTRA_CPP_SOURCES: testbitfields_cpp.cpp
|
||||
// EXTRA_SOURCES: extra-files/testbitfields_importc.c
|
||||
// CXXFLAGS(linux osx freebsd dragonflybsd): -std=c++11
|
||||
|
||||
import core.stdc.stdio;
|
||||
import core.stdc.stdlib;
|
||||
import core.stdc.string;
|
||||
|
||||
static import testbitfields_importc;
|
||||
|
||||
extern(C++) size_t getStructSize(T)();
|
||||
extern(C++) size_t getStructAlign(T)();
|
||||
extern(C++) void resetBitfield(T)(ref T data, const(char) *member);
|
||||
|
||||
bool checkType(S)()
|
||||
{
|
||||
bool different;
|
||||
if (S.sizeof != getStructSize!S)
|
||||
different = true;
|
||||
if (S.alignof != getStructAlign!S)
|
||||
different = true;
|
||||
static foreach (member; __traits(allMembers, S))
|
||||
{{
|
||||
static if (member[0] != '_' && typeof(__traits(getMember, S, member)).stringof[0] != '_')
|
||||
{
|
||||
S dummyD;
|
||||
memset(&dummyD, 0xff, S.sizeof);
|
||||
__traits(getMember, dummyD, member) = 0;
|
||||
|
||||
S* dummyC = cast(S*) malloc(getStructSize!S);
|
||||
memset(dummyC, 0xff, getStructSize!S);
|
||||
resetBitfield!S(*dummyC, member.ptr);
|
||||
if (S.sizeof == getStructSize!S && memcmp(&dummyD, dummyC, S.sizeof) != 0)
|
||||
different = true;
|
||||
free(dummyC);
|
||||
}
|
||||
}}
|
||||
if (different)
|
||||
{
|
||||
printf("Struct %s has different bitfield layout for C and D:\n", __traits(identifier, S).ptr);
|
||||
printf(" D: size=%zd align=%zd\n", S.sizeof, S.alignof);
|
||||
printf(" C: size=%zd align=%zd\n", getStructSize!S, getStructAlign!S);
|
||||
static foreach (member; __traits(allMembers, S))
|
||||
{{
|
||||
static if (member[0] != '_' && typeof(__traits(getMember, S, member)).stringof[0] != '_')
|
||||
{
|
||||
printf(" %s %s:\n", typeof(__traits(getMember, S, member)).stringof.ptr, member.ptr);
|
||||
printf(" D:");
|
||||
S dummyD;
|
||||
memset(&dummyD, 0xff, S.sizeof);
|
||||
__traits(getMember, dummyD, member) = 0;
|
||||
foreach (i; 0 .. S.sizeof)
|
||||
{
|
||||
if (i % 4 == 0)
|
||||
printf(" ");
|
||||
printf("%02X", 0xff & ~(cast(ubyte*) &dummyD)[i]);
|
||||
}
|
||||
|
||||
printf("\n C:");
|
||||
S* dummyC = cast(S*) malloc(getStructSize!S);
|
||||
memset(dummyC, 0xff, getStructSize!S);
|
||||
resetBitfield!S(*dummyC, member.ptr);
|
||||
foreach (i; 0 .. getStructSize!S)
|
||||
{
|
||||
if (i % 4 == 0)
|
||||
printf(" ");
|
||||
printf("%02X", 0xff & ~(cast(ubyte*) dummyC)[i]);
|
||||
}
|
||||
free(dummyC);
|
||||
printf("\n");
|
||||
}
|
||||
}}
|
||||
}
|
||||
return different;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int ret;
|
||||
static foreach (name; __traits(allMembers, testbitfields_importc))
|
||||
{{
|
||||
alias S = __traits(getMember, testbitfields_importc, name);
|
||||
static if (is(S == struct) && name[0] != '_')
|
||||
{
|
||||
if (checkType!S)
|
||||
ret = 1;
|
||||
}
|
||||
}}
|
||||
return ret;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue