diff --git a/src/dmd/cppmangle.d b/src/dmd/cppmangle.d index 6f4cffc32069..fbc9bb8e6239 100644 --- a/src/dmd/cppmangle.d +++ b/src/dmd/cppmangle.d @@ -1334,8 +1334,8 @@ extern(C++): case Tfloat80: c = 'e'; break; case Tbool: c = 'b'; break; case Tchar: c = 'c'; break; - case Twchar: c = 't'; break; // unsigned short (perhaps use 'Ds' ? - case Tdchar: c = 'w'; break; // wchar_t (UTF-32) (perhaps use 'Di' ? + case Twchar: p = 'D'; c = 's'; break; // since C++11 + case Tdchar: p = 'D'; c = 'i'; break; // since C++11 case Timaginary32: p = 'G'; c = 'f'; break; // 'G' means imaginary case Timaginary64: p = 'G'; c = 'd'; break; case Timaginary80: p = 'G'; c = 'e'; break; diff --git a/src/dmd/cppmanglewin.d b/src/dmd/cppmanglewin.d index 5c30d6bb17f5..19046e6887e4 100644 --- a/src/dmd/cppmanglewin.d +++ b/src/dmd/cppmanglewin.d @@ -220,27 +220,23 @@ public: case Tfloat64: buf.writeByte('N'); break; - case Tbool: - buf.writestring("_N"); - break; - case Tchar: - buf.writeByte('D'); - break; - case Tdchar: - buf.writeByte('I'); - break; - // unsigned int case Tfloat80: if (flags & IS_DMC) buf.writestring("_Z"); // DigitalMars long double else buf.writestring("_T"); // Intel long double break; + case Tbool: + buf.writestring("_N"); + break; + case Tchar: + buf.writeByte('D'); + break; case Twchar: - if (flags & IS_DMC) - buf.writestring("_Y"); // DigitalMars wchar_t - else - buf.writestring("_W"); // Visual C++ wchar_t + buf.writestring("_S"); // Visual C++ char16_t (since C++11) + break; + case Tdchar: + buf.writestring("_U"); // Visual C++ char32_t (since C++11) break; default: visit(cast(Type)type); diff --git a/test/compilable/cppmangle.d b/test/compilable/cppmangle.d index b5f315d4524c..0c5d3a89b71e 100644 --- a/test/compilable/cppmangle.d +++ b/test/compilable/cppmangle.d @@ -976,3 +976,22 @@ else version(Posix) static assert(test19278_4.mangleof == "_ZN5hello5world3yay11test19278_4Ev"); static assert(test19278_var.mangleof == "_ZN5hello5world13test19278_varE"); } + +/**************************************/ +// https://issues.dlang.org/show_bug.cgi?id=18958 +// Issue 18958 - extern(C++) wchar, dchar mangling not correct + +version(Posix) + enum __c_wchar_t : dchar; +else version(Windows) + enum __c_wchar_t : wchar; +alias wchar_t = __c_wchar_t; +extern (C++) void test_char_mangling(char, wchar, dchar, wchar_t); +version (Posix) +{ + static assert(test_char_mangling.mangleof == "_Z18test_char_manglingcDsDiw"); +} +version (Win64) +{ + static assert(test_char_mangling.mangleof == "?test_char_mangling@@YAXD_S_U_W@Z"); +} diff --git a/test/runnable/cpp_abi_tests.d b/test/runnable/cpp_abi_tests.d index 67279bfbb9af..a3f39edcc0b1 100644 --- a/test/runnable/cpp_abi_tests.d +++ b/test/runnable/cpp_abi_tests.d @@ -1,4 +1,14 @@ // EXTRA_CPP_SOURCES: cpp_abi_tests.cpp +// CXXFLAGS(linux freebsd osx 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++) { @@ -16,7 +26,9 @@ 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); @@ -32,7 +44,9 @@ 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); @@ -48,7 +62,9 @@ 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); @@ -94,7 +110,7 @@ template IsBoolean(T) template IsSomeChar(T) { - enum IsSomeChar = is(T==char) || is(T==dchar); + enum IsSomeChar = is(T==char) || is(T==wchar) || is(T==dchar) || is(T==wchar_t); } void check(T)(T actual, T expected) @@ -181,7 +197,17 @@ void main() foreach(byte val; values!byte()) check(val); foreach(ubyte val; values!ubyte()) check(val); foreach(char val; values!char()) check(val); +version(CppRuntime_DigitalMars){} else +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); diff --git a/test/runnable/cppa.d b/test/runnable/cppa.d index 6691e33f9433..e1a7220a5594 100644 --- a/test/runnable/cppa.d +++ b/test/runnable/cppa.d @@ -1,5 +1,8 @@ // PERMUTE_ARGS: -g // EXTRA_CPP_SOURCES: cppb.cpp +// CXXFLAGS(linux freebsd osx netbsd dragonflybsd): -std=c++11 + +// N.B MSVC doesn't have a C++11 switch, but it defaults to the latest fully-supported standard import core.stdc.stdio; import core.stdc.stdarg; @@ -915,13 +918,22 @@ void fuzz2() } //////// -extern(C++) void fuzz3_cppvararg(wchar arg10, wchar arg11, bool arg12); -extern(C++) void fuzz3_dvararg(wchar arg10, wchar arg11, bool arg12) +version(CppRuntime_DigitalMars) + enum UNICODE = false; +else version(CppRuntime_Microsoft) + enum UNICODE = false; //VS2013 doesn't support them +else + enum UNICODE = true; + +static if (UNICODE) +{ +extern(C++) void fuzz3_cppvararg(wchar arg10, dchar arg11, bool arg12); +extern(C++) void fuzz3_dvararg(wchar arg10, dchar arg11, bool arg12) { fuzz2_checkValues(arg10, arg11, arg12); } -extern(C++) void fuzz3_checkValues(wchar arg10, wchar arg11, bool arg12) +extern(C++) void fuzz3_checkValues(wchar arg10, dchar arg11, bool arg12) { assert(arg10 == 103); assert(arg11 == 104); @@ -931,17 +943,18 @@ extern(C++) void fuzz3_checkValues(wchar arg10, wchar arg11, bool arg12) void fuzz3() { wchar arg10 = 103; - wchar arg11 = 104; + dchar arg11 = 104; bool arg12 = false; fuzz3_dvararg(arg10, arg11, arg12); fuzz3_cppvararg(arg10, arg11, arg12); } +} void fuzz() { fuzz1(); fuzz2(); - fuzz3(); + static if (UNICODE) fuzz3(); } /****************************************/ diff --git a/test/runnable/extra-files/cpp_abi_tests.cpp b/test/runnable/extra-files/cpp_abi_tests.cpp index 64088aaf0b55..07cc09b2ee45 100644 --- a/test/runnable/extra-files/cpp_abi_tests.cpp +++ b/test/runnable/extra-files/cpp_abi_tests.cpp @@ -9,10 +9,21 @@ namespace std struct test19248 {int a;}; }; +#ifdef __DMC__ +// DMC doesn't support c++11 +#elif defined (_MSC_VER) && _MSC_VER <= 1800 +// MSVC2013 doesn't support char16_t/char32_t +#else +#define TEST_UNICODE +#endif bool passthrough(bool value) { return value; } signed char passthrough(signed char value) { return value; } unsigned char passthrough(unsigned char value) { return value; } char passthrough(char value) { return value; } +#ifdef TEST_UNICODE +char16_t passthrough(char16_t value) { return value; } +char32_t passthrough(char32_t value) { return value; } +#endif wchar_t passthrough(wchar_t value) { return value; } short passthrough(short value) { return value; } unsigned short passthrough(unsigned short value) { return value; } @@ -31,6 +42,10 @@ bool passthrough_ptr(bool *value) { return *value; } signed char passthrough_ptr(signed char *value) { return *value; } unsigned char passthrough_ptr(unsigned char *value) { return *value; } char passthrough_ptr(char *value) { return *value; } +#ifdef TEST_UNICODE +char16_t passthrough_ptr(char16_t *value) { return *value; } +char32_t passthrough_ptr(char32_t *value) { return *value; } +#endif wchar_t passthrough_ptr(wchar_t *value) { return *value; } short passthrough_ptr(short *value) { return *value; } unsigned short passthrough_ptr(unsigned short *value) { return *value; } @@ -49,6 +64,10 @@ bool passthrough_ref(bool &value) { return value; } signed char passthrough_ref(signed char &value) { return value; } unsigned char passthrough_ref(unsigned char &value) { return value; } char passthrough_ref(char &value) { return value; } +#ifdef TEST_UNICODE +char16_t passthrough_ref(char16_t &value) { return value; } +char32_t passthrough_ref(char32_t &value) { return value; } +#endif wchar_t passthrough_ref(wchar_t &value) { return value; } short passthrough_ref(short &value) { return value; } unsigned short passthrough_ref(unsigned short &value) { return value; } diff --git a/test/runnable/extra-files/cppb.cpp b/test/runnable/extra-files/cppb.cpp index 0fa6767cf782..ab1ea0a5a551 100644 --- a/test/runnable/extra-files/cppb.cpp +++ b/test/runnable/extra-files/cppb.cpp @@ -406,36 +406,30 @@ wchar_t f13289_cpp_wchar_t(wchar_t ch) return ch; } } - -#if __linux__ || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun || __NetBSD__ || __DragonFly__ -unsigned short f13289_d_wchar(unsigned short ch); -wchar_t f13289_d_dchar(wchar_t ch); -#elif _WIN32 -wchar_t f13289_d_wchar(wchar_t ch); -unsigned int f13289_d_dchar(unsigned int ch); +#ifdef __DMC__ +// DMC doesn't support c++11 +#elif defined (_MSC_VER) //&& _MSC_VER <= 1800 +// MSVC2013 doesn't support char16_t/char32_t +#else +#define TEST_UNICODE +#endif +#ifdef TEST_UNICODE +char16_t f13289_d_wchar(char16_t ch); +char32_t f13289_d_dchar(char32_t ch); #endif - wchar_t f13289_d_wchar_t(wchar_t ch); bool f13289_cpp_test() { if (!(f13289_d_wchar_t(L'e') == L'E')) return false; if (!(f13289_d_wchar_t(L'F') == L'F')) return false; -#if __linux__ || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun || __NetBSD__ || __DragonFly__ - if (!(f13289_d_wchar((unsigned short)'c') == (unsigned short)'C')) return false; - if (!(f13289_d_wchar((unsigned short)'D') == (unsigned short)'D')) return false; - if (!(f13289_d_dchar(L'e') == L'E')) return false; - if (!(f13289_d_dchar(L'F') == L'F')) return false; - return true; -#elif _WIN32 - if (!(f13289_d_wchar(L'c') == L'C')) return false; - if (!(f13289_d_wchar(L'D') == L'D')) return false; - if (!(f13289_d_dchar((unsigned int)'e') == (unsigned int)'E')) return false; - if (!(f13289_d_dchar((unsigned int)'F') == (unsigned int)'F')) return false; - return true; -#else - return false; +#ifdef TEST_UNICODE + if (!(f13289_d_wchar(u'c') == u'C')) return false; + if (!(f13289_d_wchar(u'D') == u'D')) return false; + if (!(f13289_d_dchar(U'e') == U'E')) return false; + if (!(f13289_d_dchar(U'F') == U'F')) return false; #endif + return true; } /******************************************/ @@ -593,17 +587,13 @@ void fuzz2_cppvararg(uint64_t arg10, uint64_t arg11, bool arg12) fuzz2_checkValues(arg10, arg11, arg12); } -#if __linux__ || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun || __NetBSD__ || __DragonFly__ -#define wchar unsigned short -#elif _WIN32 -#define wchar wchar_t -#endif - -void fuzz3_checkValues(wchar arg10, wchar arg11, bool arg12); -void fuzz3_cppvararg(wchar arg10, wchar arg11, bool arg12) +#ifdef TEST_UNICODE +void fuzz3_checkValues(char16_t arg10, char32_t arg11, bool arg12); +void fuzz3_cppvararg(char16_t arg10, char32_t arg11, bool arg12) { fuzz3_checkValues(arg10, arg11, arg12); } +#endif /******************************************/