// EXTRA_CPP_SOURCES: cpp_abi_tests.cpp // CXXFLAGS(linux freebsd osx openbsd netbsd dragonflybsd): -std=c++11 // N.B MSVC doesn't have a C++11 switch, but it defaults to the latest fully-supported standard // N.B MSVC 2013 doesn't support char16_t/char32_t version(Posix) enum __c_wchar_t : dchar; else version(Windows) enum __c_wchar_t : wchar; alias wchar_t = __c_wchar_t; extern(C++) { struct S { float a = 1; } struct S18784 { int i; this(int); } extern(C++, std) { struct test19248_ {int a = 42;} } extern(C++, `std`) { struct test19248 {int a = 34;} } struct Sdtor { extern __gshared int counter; ~this(); } void consume(Sdtor); void consume2(Sdtor value){} void doConsume2(ref Sdtor); struct SPack(Args...) { int i; } alias SInt = SPack!int; bool passthrough(bool value); byte passthrough(byte value); ubyte passthrough(ubyte value); char passthrough(char value); wchar passthrough(wchar value); dchar passthrough(dchar value); wchar_t passthrough(wchar_t value); short passthrough(short value); ushort passthrough(ushort value); int passthrough(int value); uint passthrough(uint value); long passthrough(long value); ulong passthrough(ulong value); float passthrough(float value); double passthrough(double value); S passthrough(S value); test19248 passthrough(const(test19248) value); std.test19248_ passthrough(const(std.test19248_) value); SInt passthrough(SInt value); bool passthrough_ptr(bool *value); byte passthrough_ptr(byte *value); ubyte passthrough_ptr(ubyte *value); char passthrough_ptr(char *value); wchar passthrough_ptr(wchar *value); dchar passthrough_ptr(dchar *value); wchar_t passthrough_ptr(wchar_t *value); short passthrough_ptr(short *value); ushort passthrough_ptr(ushort *value); int passthrough_ptr(int *value); uint passthrough_ptr(uint *value); long passthrough_ptr(long *value); ulong passthrough_ptr(ulong *value); float passthrough_ptr(float *value); double passthrough_ptr(double *value); S passthrough_ptr(S *value); test19248 passthrough_ptr(const(test19248)* value); std.test19248_ passthrough_ptr(const(std.test19248_)* value); SInt passthrough_ptr(SInt *value); bool passthrough_ref(ref bool value); byte passthrough_ref(ref byte value); ubyte passthrough_ref(ref ubyte value); char passthrough_ref(ref char value); wchar passthrough_ref(ref wchar value); dchar passthrough_ref(ref dchar value); wchar_t passthrough_ref(ref wchar_t value); short passthrough_ref(ref short value); ushort passthrough_ref(ref ushort value); int passthrough_ref(ref int value); uint passthrough_ref(ref uint value); long passthrough_ref(ref long value); ulong passthrough_ref(ref ulong value); float passthrough_ref(ref float value); double passthrough_ref(ref double value); S passthrough_ref(ref S value); test19248 passthrough_ref(ref const(test19248) value); std.test19248_ passthrough_ref(ref const(std.test19248_) value); SInt passthrough_ref(ref SInt value); } template IsSigned(T) { enum IsSigned = is(T==byte) || is(T==short) || is(T==int) || is(T==long); } template IsUnsigned(T) { enum IsUnsigned = is(T==ubyte) || is(T==ushort) || is(T==uint) || is(T==ulong); } template IsIntegral(T) { enum IsIntegral = IsSigned!T || IsUnsigned!T; } template IsFloatingPoint(T) { enum IsFloatingPoint = is(T==float) || is(T==double) || is(T==real); } template IsBoolean(T) { enum IsBoolean = is(T==bool); } template IsSomeChar(T) { enum IsSomeChar = is(T==char) || is(T==wchar) || is(T==dchar) || is(T==wchar_t); } void check(T)(T actual, T expected) { assert(actual is expected); } void check(T)(T value) { check(passthrough(value), value); check(passthrough_ptr(&value), value); check(passthrough_ref(value), value); } T[] values(T)() { T[] values; static if(IsBoolean!T) { values ~= true; values ~= false; } else static if(IsSomeChar!T) { values ~= T.init; values ~= T('a'); values ~= T('z'); } else { values ~= T(0); values ~= T(1); static if(IsIntegral!T) { static if(IsSigned!T) values ~= T.min; values ~= T.max; } else static if(IsFloatingPoint!T) { values ~= T.nan; values ~= T.min_normal; values ~= T.max; } else { assert(0); } } return values; } extern(C++, `ns1`) { // C++: `const char*, const char**` int constFunction1(const(char)*, const(char)**); // C++: `const char*, const char* const*` int constFunction2(const(char)*, const(char*)*); // C++: `const char* const, const char* const* const*` int constFunction3(const(char*), const(char**)*); // C++: `const char* const, const char* const* const* const` int constFunction4(const(char*), const(char***)); } extern(C++) { // https://issues.dlang.org/show_bug.cgi?id=19563 struct SmallStruct { int i; this(int i) { this.i = i; } this(ref const SmallStruct); // implemented in C++ } void smallStructTest(SmallStruct p); void smallStructCallBack(SmallStruct p) { assert(p.i == 62); } } /*********************************************/ // https://issues.dlang.org/show_bug.cgi?id=23195 extern (C++) { struct FF { float x, y; ~this() { } } float draw(FF min, FF max); void test23195() { FF a = { 1, 2 }; FF b = { 3, 4 }; float f = draw(a, b); assert(f == 1234); } /*********************/ struct FF2 { float x, y; this(int i) { } } float draw2(FF2 min, FF2 max); void test23195_2() { FF2 a; a.x = 1; a.y = 2; FF2 b; b.x = 3; b.y = 4; float f = draw2(a, b); assert(f == 1234); } } /*********************************************/ void main() { foreach(bool val; values!bool()) check(val); foreach(byte val; values!byte()) check(val); foreach(ubyte val; values!ubyte()) check(val); foreach(char val; values!char()) check(val); version(CppRuntime_Microsoft) { // TODO: figure out how to detect VS2013 which doesn't support char16_t/char32_t } else { foreach(wchar val; values!wchar()) check(val); foreach(dchar val; values!dchar()) check(val); } foreach(wchar_t val; values!wchar_t()) check(val); foreach(short val; values!short()) check(val); foreach(ushort val; values!ushort()) check(val); foreach(int val; values!int()) check(val); foreach(uint val; values!uint()) check(val); foreach(long val; values!long()) check(val); foreach(ulong val; values!ulong()) check(val); foreach(float val; values!float()) check(val); foreach(double val; values!double()) check(val); check(S()); check(test19248()); check(std.test19248_()); check(SInt()); assert(constFunction1(null, null) == 1); assert(constFunction2(null, null) == 2); assert(constFunction3(null, null) == 3); assert(constFunction4(null, null) == 42); auto ss = SmallStruct(42); smallStructTest(ss); assert(ss.i == 42); assert(S18784(1).i == 1); { Sdtor sd; assert(Sdtor.counter == 0); consume(sd); assert(Sdtor.counter == 1); doConsume2(sd); assert(Sdtor.counter == 2); } test23195(); test23195_2(); }