diff --git a/changelog/fix18053.dd b/changelog/fix18053.dd new file mode 100644 index 000000000000..3fe0298c6e1e --- /dev/null +++ b/changelog/fix18053.dd @@ -0,0 +1,16 @@ +Fix Issue 18053 - mangle long/ulong as int64_t/uint64_t + +This is a breaking change (on OSX 64). + +Due to the erratic implementation defined behavior of C++ name mangling, it was +difficult to get D's long/ulong to portably match up with the corresponding +C++ compiler. + +By instead relying on how the corresponding C++ compiler mangled int64_t/uint64_t +it makes the C++ side of the D<=>C++ interface much simpler. + +For the current platforms dmd supports, only the OSX 64 bit mangling changes. In +this case from 'm' to 'y'. + +Note: + int64_t and uint64_t are defined in stdint.h diff --git a/src/dmd/cppmangle.d b/src/dmd/cppmangle.d index 954cfd51fe2a..2dc635e128ad 100644 --- a/src/dmd/cppmangle.d +++ b/src/dmd/cppmangle.d @@ -815,10 +815,10 @@ public: case Tuns32: c = 'j'; break; case Tfloat32: c = 'f'; break; case Tint64: - c = (Target.c_longsize == 8 ? 'l' : 'x'); + c = Target.c_longsize == 8 ? Target.int64Mangle : 'x'; break; case Tuns64: - c = (Target.c_longsize == 8 ? 'm' : 'y'); + c = Target.c_longsize == 8 ? Target.uint64Mangle : 'y'; break; case Tint128: c = 'n'; break; case Tuns128: c = 'o'; break; diff --git a/src/dmd/target.d b/src/dmd/target.d index 85e62f0a4337..ef0cd234f362 100644 --- a/src/dmd/target.d +++ b/src/dmd/target.d @@ -6,6 +6,8 @@ * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/target.d, _target.d) + * Documentation: https://dlang.org/phobos/ddmd_target.html + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/ddmd/target.d */ module dmd.target; @@ -29,16 +31,21 @@ import dmd.root.outbuffer; */ struct Target { - extern (C++) static __gshared int ptrsize; - extern (C++) static __gshared int realsize; // size a real consumes in memory - extern (C++) static __gshared int realpad; // 'padding' added to the CPU real size to bring it up to realsize - extern (C++) static __gshared int realalignsize; // alignment for reals - extern (C++) static __gshared bool reverseCppOverloads; // with dmc and cl, overloaded functions are grouped and in reverse order - extern (C++) static __gshared bool cppExceptions; // set if catching C++ exceptions is supported - extern (C++) static __gshared int c_longsize; // size of a C 'long' or 'unsigned long' type - extern (C++) static __gshared int c_long_doublesize; // size of a C 'long double' - extern (C++) static __gshared int classinfosize; // size of 'ClassInfo' - extern (C++) static __gshared ulong maxStaticDataSize; // maximum size of static data + extern (C++) __gshared + { + int ptrsize; + int realsize; /// size a real consumes in memory + int realpad; /// 'padding' added to the CPU real size to bring it up to realsize + int realalignsize; /// alignment for reals + bool reverseCppOverloads; /// with dmc and cl, overloaded functions are grouped and in reverse order + bool cppExceptions; /// set if catching C++ exceptions is supported + char int64Mangle; /// mangling character for C++ int64_t + char uint64Mangle; /// mangling character for C++ uint64_t + int c_longsize; /// size of a C 'long' or 'unsigned long' type + int c_long_doublesize; /// size of a C 'long double' + int classinfosize; /// size of 'ClassInfo' + ulong maxStaticDataSize; /// maximum size of static data + } extern (C++) struct FPTypeProperties(T) { @@ -135,6 +142,9 @@ struct Target cppExceptions = global.params.isLinux || global.params.isFreeBSD || global.params.isOSX; + + int64Mangle = global.params.isOSX ? 'x' : 'l'; + uint64Mangle = global.params.isOSX ? 'y' : 'm'; } /****************************** diff --git a/src/dmd/target.h b/src/dmd/target.h index 44ef2a347a12..838306745dbd 100644 --- a/src/dmd/target.h +++ b/src/dmd/target.h @@ -33,6 +33,8 @@ struct Target static int realalignsize; // alignment for reals static bool reverseCppOverloads; // with dmc and cl, overloaded functions are grouped and in reverse order static bool cppExceptions; // set if catching C++ exceptions is supported + static char int64Mangle; // mangling character for C++ int64_t + static char uint64Mangle; // mangling character for C++ uint64_t static int c_longsize; // size of a C 'long' or 'unsigned long' type static int c_long_doublesize; // size of a C 'long double' static int classinfosize; // size of 'ClassInfo' diff --git a/test/runnable/extra-files/cppb.cpp b/test/runnable/extra-files/cppb.cpp index 7574c5fba721..3a16c24b53c7 100644 --- a/test/runnable/extra-files/cppb.cpp +++ b/test/runnable/extra-files/cppb.cpp @@ -32,6 +32,7 @@ headers. #define _GLIBCXX_USE_CXX11_ABI 0 #include +#include #include #include #include @@ -567,20 +568,15 @@ Visitor2* getVisitor2() /******************************************/ // issues detected by fuzzer -#if _LP64 -#define longlong long -#else -#define longlong long long -#endif -void fuzz1_checkValues(longlong arg10, longlong arg11, bool arg12); -void fuzz1_cppvararg(longlong arg10, longlong arg11, bool arg12) +void fuzz1_checkValues(int64_t arg10, int64_t arg11, bool arg12); +void fuzz1_cppvararg(int64_t arg10, int64_t arg11, bool arg12) { fuzz1_checkValues(arg10, arg11, arg12); } -void fuzz2_checkValues(unsigned longlong arg10, unsigned longlong arg11, bool arg12); -void fuzz2_cppvararg(unsigned longlong arg10, unsigned longlong arg11, bool arg12) +void fuzz2_checkValues(uint64_t arg10, uint64_t arg11, bool arg12); +void fuzz2_cppvararg(uint64_t arg10, uint64_t arg11, bool arg12) { fuzz2_checkValues(arg10, arg11, arg12); } @@ -805,7 +801,7 @@ void test15802b() // 16536 - mangling mismatch on OSX #if defined(__APPLE__) -__UINTMAX_TYPE__ pass16536(__UINTMAX_TYPE__ a) +uint64_t pass16536(uint64_t a) { return a; } diff --git a/test/runnable/extra-files/externmangle.cpp b/test/runnable/extra-files/externmangle.cpp index 473ac627b65b..31ae94f65f62 100644 --- a/test/runnable/extra-files/externmangle.cpp +++ b/test/runnable/extra-files/externmangle.cpp @@ -194,17 +194,10 @@ int Module::dim(Array* arr) return arr->dim; } -#if _LP64 -unsigned long testlongmangle(int32_t a, uint32_t b, long c, unsigned long d) +uint64_t testlongmangle(int a, unsigned int b, int64_t c, uint64_t d) { return a + b + c + d; } -#else -unsigned long long testlongmangle(int a, unsigned int b, long long c, unsigned long long d) -{ - return a + b + c + d; -} -#endif int test31[2][2][2] = {1, 1, 1, 1, 1, 1, 1, 1}; int *test32 = 0;