Skip to content
4 changes: 2 additions & 2 deletions src/dmd/cppmangle.d
Original file line number Diff line number Diff line change
Expand Up @@ -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
Comment thread
thewilsonator marked this conversation as resolved.
case Timaginary32: p = 'G'; c = 'f'; break; // 'G' means imaginary
case Timaginary64: p = 'G'; c = 'd'; break;
case Timaginary80: p = 'G'; c = 'e'; break;
Expand Down
24 changes: 10 additions & 14 deletions src/dmd/cppmanglewin.d
Original file line number Diff line number Diff line change
Expand Up @@ -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
Comment thread
TurkeyMan marked this conversation as resolved.
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);
Expand Down
19 changes: 19 additions & 0 deletions test/compilable/cppmangle.d
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
28 changes: 27 additions & 1 deletion test/runnable/cpp_abi_tests.d
Original file line number Diff line number Diff line change
@@ -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++) {

Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Comment thread
TurkeyMan marked this conversation as resolved.
}

void check(T)(T actual, T expected)
Expand Down Expand Up @@ -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);
Expand Down
23 changes: 18 additions & 5 deletions test/runnable/cppa.d
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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();
}

/****************************************/
Expand Down
19 changes: 19 additions & 0 deletions test/runnable/extra-files/cpp_abi_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you're going to have to wrap these in #if ! __DMC__, win32 fails with duplicate definition. Ditto for below.

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; }
Expand All @@ -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; }
Expand All @@ -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; }
Expand Down
50 changes: 20 additions & 30 deletions test/runnable/extra-files/cppb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

/******************************************/
Expand Down Expand Up @@ -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

/******************************************/

Expand Down