Fix bugzilla 24577 - Struct with constructor returned from C++ wrong

The test case is copied from LDC, where it already worked. It also has
an additional test for a member struct with constructor.
This commit is contained in:
Tim Schendekehl 2024-06-08 14:51:12 +02:00 committed by The Dlang Bot
parent db92f687e4
commit 56a21cba42
3 changed files with 194 additions and 0 deletions

View file

@ -1009,6 +1009,8 @@ extern (C++) struct Target
auto sd = ts.sym; auto sd = ts.sym;
if (tf.linkage == LINK.cpp && needsThis) if (tf.linkage == LINK.cpp && needsThis)
return true; return true;
if (tf.linkage == LINK.cpp && sd.ctor)
return true;
if (!sd.isPOD() || sz > 8) if (!sd.isPOD() || sz > 8)
return true; return true;
if (sd.fields.length == 0) if (sd.fields.length == 0)

View file

@ -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);

View file

@ -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();
}