forked from dlang/dmd
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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.
- Loading branch information
Showing
3 changed files
with
194 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
74 changes: 74 additions & 0 deletions
74
compiler/test/runnable_cxx/extra-files/cpp_nonpod_byval.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, ¶m); \ | ||
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); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, ¶m); | ||
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(); | ||
} |