mirror of
https://github.com/dlang/dmd.git
synced 2025-04-27 05:30:13 +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
84
compiler/test/runnable_cxx/extra-files/testbitfields_cpp.cpp
Normal file
84
compiler/test/runnable_cxx/extra-files/testbitfields_cpp.cpp
Normal file
|
@ -0,0 +1,84 @@
|
|||
extern "C"
|
||||
{
|
||||
#include "testbitfields_importc.c"
|
||||
}
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
template<typename T>
|
||||
size_t getStructSize();
|
||||
template<typename T>
|
||||
size_t getStructAlign();
|
||||
template<typename T>
|
||||
void resetBitfield(T &data, const char *member);
|
||||
|
||||
#define BEGIN_STRUCT(S) \
|
||||
template<> \
|
||||
size_t getStructSize<S>() \
|
||||
{ \
|
||||
return sizeof(S); \
|
||||
} \
|
||||
template<> \
|
||||
size_t getStructAlign<S>() \
|
||||
{ \
|
||||
return alignof(S); \
|
||||
} \
|
||||
template<> \
|
||||
void resetBitfield<S>(S &data, const char *member) \
|
||||
{
|
||||
|
||||
#define FIELD(name) if (strcmp(member, #name) == 0) data.name = 0;
|
||||
#define END_STRUCT }
|
||||
|
||||
BEGIN_STRUCT(T0) FIELD(x) END_STRUCT
|
||||
BEGIN_STRUCT(T1) FIELD(x) END_STRUCT
|
||||
BEGIN_STRUCT(T2) FIELD(x) END_STRUCT
|
||||
BEGIN_STRUCT(T3) FIELD(a) FIELD(b) FIELD(c) FIELD(d) FIELD(x) END_STRUCT
|
||||
BEGIN_STRUCT(T4) FIELD(a) FIELD(b) FIELD(c) FIELD(d) FIELD(e) FIELD(f) FIELD(g) FIELD(h) FIELD(x) END_STRUCT
|
||||
BEGIN_STRUCT(T5) FIELD(a) FIELD(b) FIELD(c) FIELD(d) FIELD(e) FIELD(f) FIELD(g) FIELD(x) END_STRUCT
|
||||
BEGIN_STRUCT(S1) FIELD(f) END_STRUCT
|
||||
BEGIN_STRUCT(S2) FIELD(x) FIELD(y) END_STRUCT
|
||||
BEGIN_STRUCT(S3) FIELD(c) FIELD(x) FIELD(y) END_STRUCT
|
||||
BEGIN_STRUCT(S4) FIELD(x) FIELD(y) END_STRUCT
|
||||
BEGIN_STRUCT(S5) FIELD(x) FIELD(y) END_STRUCT
|
||||
BEGIN_STRUCT(S6) FIELD(x) FIELD(y) END_STRUCT
|
||||
BEGIN_STRUCT(S7) FIELD(x) FIELD(y) FIELD(z) END_STRUCT
|
||||
BEGIN_STRUCT(S8) FIELD(a) FIELD(b) FIELD(c) END_STRUCT
|
||||
BEGIN_STRUCT(S8A) FIELD(b) FIELD(c) END_STRUCT
|
||||
BEGIN_STRUCT(S8B) FIELD(a) FIELD(b) FIELD(c) END_STRUCT
|
||||
BEGIN_STRUCT(S8C) FIELD(a) FIELD(b) END_STRUCT
|
||||
BEGIN_STRUCT(S9) FIELD(a) FIELD(b) FIELD(c) END_STRUCT
|
||||
//BEGIN_STRUCT(S10) END_STRUCT
|
||||
//BEGIN_STRUCT(S11) END_STRUCT
|
||||
BEGIN_STRUCT(S12) FIELD(x) END_STRUCT
|
||||
BEGIN_STRUCT(S13) FIELD(x) FIELD(x1) FIELD(x2) FIELD(x3) FIELD(x4) FIELD(w) END_STRUCT
|
||||
BEGIN_STRUCT(S14) FIELD(a) FIELD(b) FIELD(c) END_STRUCT
|
||||
BEGIN_STRUCT(S15) FIELD(a) FIELD(b) FIELD(c) END_STRUCT
|
||||
BEGIN_STRUCT(S16) END_STRUCT
|
||||
BEGIN_STRUCT(S17) FIELD(a) END_STRUCT
|
||||
BEGIN_STRUCT(S18) FIELD(a) FIELD(b) END_STRUCT
|
||||
BEGIN_STRUCT(A0) FIELD(a) FIELD(b) FIELD(c) END_STRUCT
|
||||
BEGIN_STRUCT(A1) FIELD(a) FIELD(b) FIELD(c) END_STRUCT
|
||||
BEGIN_STRUCT(A2) FIELD(a) FIELD(b) FIELD(c) FIELD(d)
|
||||
FIELD(e) END_STRUCT
|
||||
BEGIN_STRUCT(A3) FIELD(a) FIELD(b) FIELD(c) FIELD(d)
|
||||
FIELD(e) END_STRUCT
|
||||
BEGIN_STRUCT(A4) FIELD(a) FIELD(b)
|
||||
FIELD(c) END_STRUCT
|
||||
BEGIN_STRUCT(A5) FIELD(a) FIELD(b) END_STRUCT
|
||||
BEGIN_STRUCT(A6) FIELD(a) FIELD(b) END_STRUCT
|
||||
BEGIN_STRUCT(A7) FIELD(a) FIELD(b) FIELD(c)
|
||||
FIELD(d) END_STRUCT
|
||||
BEGIN_STRUCT(A8) FIELD(a) FIELD(b)
|
||||
FIELD(c) END_STRUCT
|
||||
BEGIN_STRUCT(A9) FIELD(a) FIELD(b)
|
||||
FIELD(c) FIELD(d)
|
||||
FIELD(e) FIELD(f) END_STRUCT
|
||||
BEGIN_STRUCT(A10) FIELD(a) FIELD(b) END_STRUCT
|
||||
BEGIN_STRUCT(A11) FIELD(a) FIELD(b) FIELD(c) FIELD(d)
|
||||
END_STRUCT
|
||||
BEGIN_STRUCT(Issue24592a) FIELD(a) FIELD(b) FIELD(c) END_STRUCT
|
||||
BEGIN_STRUCT(Issue24592b) FIELD(x) FIELD(a) FIELD(b) FIELD(c) END_STRUCT
|
||||
BEGIN_STRUCT(Issue24592c) FIELD(a) FIELD(b) FIELD(c) FIELD(d) FIELD(e) FIELD(f) END_STRUCT
|
||||
BEGIN_STRUCT(Issue24592d) FIELD(a) FIELD(b) FIELD(c) FIELD(d) FIELD(e) FIELD(f) END_STRUCT
|
|
@ -0,0 +1,52 @@
|
|||
|
||||
struct T0 { char x:1; };
|
||||
struct T1 { short x:1; };
|
||||
struct T2 { int x:1; };
|
||||
struct T3 { char a,b,c,d; long long x:1; };
|
||||
struct T4 { char a,b,c,d,e,f,g,h; long long x:1; };
|
||||
struct T5 { char a,b,c,d,e,f,g; long long x:1; };
|
||||
struct S1 { long long int f:1; };
|
||||
struct S2 { int x:1; int y:1; };
|
||||
struct S3 { short c; int x:1; unsigned y:1; };
|
||||
struct S4 { int x:1; short y:1; };
|
||||
struct S5 { short x:1; int y:1; };
|
||||
struct S6 { short x:1; short y:1; };
|
||||
struct S7 { short x:1; int y:1; long long z:1; };
|
||||
struct S8 { char a; char b:1; short c:2; };
|
||||
struct S8A { char b:1; short c:2; };
|
||||
struct S8B { char a; short b:1; char c:2; };
|
||||
struct S8C { char a; int b:1; };
|
||||
struct S9 { char a; char b:2; short c:9; };
|
||||
//struct S10 { };
|
||||
//struct S11 { int :0; };
|
||||
struct S12 { int :0; int x; };
|
||||
struct S13 { unsigned x:12; unsigned x1:1; unsigned x2:1; unsigned x3:1; unsigned x4:1; int w; };
|
||||
struct S14 { char a; char b:4; int c:30; };
|
||||
struct S15 { char a; char b:2; int c:9; };
|
||||
struct S16 { int :32; };
|
||||
struct S17 { int a:32; };
|
||||
struct S18 { char a; long long :0; char b; };
|
||||
struct A0 { int a; long long b:34, c:4; };
|
||||
struct A1 { int a; unsigned b:11; int c; };
|
||||
struct A2 { int a; unsigned b:11, c:5, d:16;
|
||||
int e; };
|
||||
struct A3 { int a; unsigned b:11, c:5, :0, d:16;
|
||||
int e; };
|
||||
struct A4 { int a:8; short b:7;
|
||||
unsigned int c:29; };
|
||||
struct A5 { char a:7, b:2; };
|
||||
struct A6 { char a:7; short b:2; };
|
||||
struct A7 { short a:8; long b:16; int c;
|
||||
char d:7; };
|
||||
struct A8 { short a:8; long b:16; int :0;
|
||||
char c:7; };
|
||||
struct A9 { unsigned short a:8; long b:16;
|
||||
unsigned long c:29; long long d:9;
|
||||
unsigned long e:2, f:31; };
|
||||
struct A10 { unsigned short a:8; char b; };
|
||||
struct A11 { char a; int b:5, c:11, :0, d:8;
|
||||
struct { int ee:8; } e; };
|
||||
struct Issue24592a { unsigned long long a:20, b:20, c:24; };
|
||||
struct Issue24592b { unsigned int x; unsigned long long a:20, b:20, c:24; };
|
||||
struct Issue24592c { unsigned long long a:20, b:32, c:32, d:32, e:32, f:32; };
|
||||
struct Issue24592d { unsigned long long a:10, b:16, c:16, d:16, e:16, f:16; };
|
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