Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Issue 18958 - extern(C++) wchar, dchar mangling not correct #8342

Merged
merged 13 commits into from
May 21, 2019
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
thewilsonator marked this conversation as resolved.
Show resolved Hide 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
TurkeyMan marked this conversation as resolved.
Show resolved Hide 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);
TurkeyMan marked this conversation as resolved.
Show resolved Hide 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
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