mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 21:21:48 +03:00

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.
90 lines
3 KiB
D
90 lines
3 KiB
D
// 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;
|
|
}
|