Skip to content

Commit

Permalink
Fix bugzilla 24577 - Struct with constructor returned from C++ wrong
Browse files Browse the repository at this point in the history
The test case is copied from LDC, where it already worked. It also has
an additional test for a member struct with constructor.
  • Loading branch information
tim-dlang authored and dlang-bot committed Jun 8, 2024
1 parent db92f68 commit 56a21cb
Show file tree
Hide file tree
Showing 3 changed files with 194 additions and 0 deletions.
2 changes: 2 additions & 0 deletions compiler/src/dmd/target.d
Original file line number Diff line number Diff line change
Expand Up @@ -1009,6 +1009,8 @@ extern (C++) struct Target
auto sd = ts.sym;
if (tf.linkage == LINK.cpp && needsThis)
return true;
if (tf.linkage == LINK.cpp && sd.ctor)
return true;
if (!sd.isPOD() || sz > 8)
return true;
if (sd.fields.length == 0)
Expand Down
74 changes: 74 additions & 0 deletions compiler/test/runnable_cxx/extra-files/cpp_nonpod_byval.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
extern "C" int printf(const char *, ...);

#define Foo(T) \
T fooD(T param); \
T fooCpp(T param) \
{ \
printf("fooCpp %d [%p]\n", param.a, &param); \
return fooD(T{2 * param.a}); \
}

struct POD
{
int a;
};
Foo(POD);

struct CtorOnly
{
int a;
CtorOnly() : a(0) {}
CtorOnly(int a) : a(a) {}
};
Foo(CtorOnly);

struct DtorOnly
{
int a;
~DtorOnly(); // implemented in D
};
Foo(DtorOnly);

struct CtorDtor
{
int a;
CtorDtor(int a) : a(a) {}
~CtorDtor(); // implemented in D
};
Foo(CtorDtor);

struct Copy
{
int a;
Copy(int a) : a(a) {}
~Copy(); // implemented in D
Copy(const Copy &rhs) : a(rhs.a) { printf("cppcpy %d [%p]\n", a, this); }
};
Foo(Copy);

struct CopyAndMove
{
int a;
CopyAndMove(int a) : a(a) {}
~CopyAndMove(); // implemented in D
CopyAndMove(const CopyAndMove &rhs) : a(rhs.a) { printf("cppcpy %d [%p]\n", a, this); }
CopyAndMove(CopyAndMove &&) = default;
};
Foo(CopyAndMove);

struct MoveOnly
{
int a;
MoveOnly(int a) : a(a) {}
~MoveOnly(); // implemented in D
MoveOnly(const MoveOnly &) = delete;
MoveOnly(MoveOnly &&) = default;
};
Foo(MoveOnly);

struct MemberWithCtor
{
int a;
CtorOnly m;
};
Foo(MemberWithCtor);
118 changes: 118 additions & 0 deletions compiler/test/runnable_cxx/nonpod_byval.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// EXTRA_CPP_SOURCES: cpp_nonpod_byval.cpp
// CXXFLAGS(linux osx freebsd dragonflybsd): -std=c++11

extern (C) int printf(const(char)*, ...);

extern (C++):

template Foo(T)
{
T fooCpp(T param); // calls fooD() with a new, doubled literal

T fooD(T param)
{
printf("fooD %d [%p]\n", param.a, &param);
assert(param.a == 2 * 123);
static if (__traits(compiles, { T copy = param; }))
return param; // invokes postblit
else
return T(param.a);
}
}

void test(T)()
{
printf(".: %.*s\n", cast(int) T.stringof.length, T.stringof.ptr);

{
auto result = fooCpp(T(123));
assert(result.a == 246);
}

static if (__traits(hasMember, T, "numDtor"))
{
// fooCpp param + fooD param + result => 3 T instances.
// There may be an additional destruction of the moved-from T literal
// in fooCpp, depending on in-place construction vs. move.
assert(T.numDtor == 3 || T.numDtor == 4);
}
}

struct POD
{
int a;
}
mixin Foo!POD;

struct CtorOnly
{
int a;
this(int a) { this.a = a; }
}
mixin Foo!CtorOnly;

struct DtorOnly
{
static __gshared int numDtor = 0;
int a;
~this() { printf("dtor %d [%p]\n", a, &this); ++numDtor; }
}
mixin Foo!DtorOnly;

struct CtorDtor
{
static __gshared int numDtor = 0;
int a;
this(int a) { this.a = a; }
~this() { printf("dtor %d [%p]\n", a, &this); ++numDtor; }
}
mixin Foo!CtorDtor;

struct Copy
{
static __gshared int numDtor = 0;
int a;
this(int a) { this.a = a; }
~this() { printf("dtor %d [%p]\n", a, &this); ++numDtor; }
this(this) { printf("post %d [%p]\n", a, &this); }
}
mixin Foo!Copy;

struct CopyAndMove
{
static __gshared int numDtor = 0;
int a;
this(int a) { this.a = a; }
~this() { printf("dtor %d [%p]\n", a, &this); ++numDtor; }
this(this) { printf("post %d [%p]\n", a, &this); }
}
mixin Foo!CopyAndMove;

struct MoveOnly
{
static __gshared int numDtor = 0;
int a;
this(int a) { this.a = a; }
~this() { printf("dtor %d [%p]\n", a, &this); ++numDtor; }
this(this) @disable;
}
mixin Foo!MoveOnly;

struct MemberWithCtor
{
int a;
CtorOnly m;
}
mixin Foo!MemberWithCtor;

void main()
{
test!POD();
test!CtorOnly();
test!DtorOnly();
test!CtorDtor();
test!Copy();
test!CopyAndMove();
test!MoveOnly();
test!MemberWithCtor();
}

0 comments on commit 56a21cb

Please sign in to comment.