From d4f55d414f88bade6315b516193e1b840d6adb70 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Tue, 25 Dec 2018 00:34:50 +0100 Subject: [PATCH] cppmangle.d: Fix substitution logic in writeBasicType() Specifically fixes nullptr_t and target-specific mangling. Later on, this will also work for char16_t and char32_t as well. --- src/dmd/cppmangle.d | 109 +++++++++++++---------------- test/runnable/cppa.d | 13 ++++ test/runnable/extra-files/cppb.cpp | 13 ++++ 3 files changed, 75 insertions(+), 60 deletions(-) diff --git a/src/dmd/cppmangle.d b/src/dmd/cppmangle.d index 90ef08b2320e..bb749a285615 100644 --- a/src/dmd/cppmangle.d +++ b/src/dmd/cppmangle.d @@ -44,6 +44,7 @@ import dmd.root.rootobject; import dmd.target; import dmd.tokens; import dmd.typesem; +import dmd.utils; import dmd.visitor; @@ -1081,16 +1082,16 @@ private final class CppMangleVisitor : Visitor } /****** - * Write out 1 or 2 character basic type mangling. + * Write out basic type mangling. * Handle const and substitutions. * Params: * t = type to mangle - * p = if not 0, then character prefix - * c = mangling character + * str = mangling string + * builtin = true if handling C++ builtin type */ - void writeBasicType(Type t, char p, char c) + void writeBasicType(Type t, const(char)[] str, bool builtin) { - if (p || t.isConst()) + if (!builtin || t.isConst()) { if (substitute(t)) return; @@ -1098,9 +1099,7 @@ private final class CppMangleVisitor : Visitor append(t); } CV_qualifiers(t); - if (p) - buf.writeByte(p); - buf.writeByte(c); + buf.writestring(str); } @@ -1221,7 +1220,10 @@ extern(C++): if (t.isImmutable() || t.isShared()) return error(t); - writeBasicType(t, 'D', 'n'); + version (all) + writeBasicType(t, "Dn", true); // Gnu ABI v.7 + else + writeBasicType(t, "Dn", false); // Gnu ABI v.6 } override void visit(TypeBasic t) @@ -1259,58 +1261,45 @@ extern(C++): * Ds char16_t * u # vendor extended type */ - char c; - char p = 0; + + // Handle any target-specific basic types. + if (auto tm = target.cppTypeMangle(t)) + { + bool builtin = (t.ty == Tvoid || t.ty == Tbool || t.isintegral() || t.isreal()); + writeBasicType(t, tm.toDString(), builtin); + return; + } + switch (t.ty) { - case Tvoid: c = 'v'; break; - case Tint8: c = 'a'; break; - case Tuns8: c = 'h'; break; - case Tint16: c = 's'; break; - case Tuns16: c = 't'; break; - case Tint32: c = 'i'; break; - case Tuns32: c = 'j'; break; - case Tfloat32: c = 'f'; break; - case Tint64: - c = target.c_longsize == 8 ? 'l' : 'x'; - break; - case Tuns64: - c = target.c_longsize == 8 ? 'm' : 'y'; - break; - case Tint128: c = 'n'; break; - case Tuns128: c = 'o'; break; - case Tfloat64: c = 'd'; break; - 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 Timaginary32: p = 'G'; c = 'f'; break; // 'G' means imaginary - case Timaginary64: p = 'G'; c = 'd'; break; - case Timaginary80: p = 'G'; c = 'e'; break; - case Tcomplex32: p = 'C'; c = 'f'; break; // 'C' means complex - case Tcomplex64: p = 'C'; c = 'd'; break; - case Tcomplex80: p = 'C'; c = 'e'; break; + case Tvoid: return writeBasicType(t, "v", true); + case Tint8: return writeBasicType(t, "a", true); + case Tuns8: return writeBasicType(t, "h", true); + case Tint16: return writeBasicType(t, "s", true); + case Tuns16: return writeBasicType(t, "t", true); + case Tint32: return writeBasicType(t, "i", true); + case Tuns32: return writeBasicType(t, "j", true); + case Tfloat32: return writeBasicType(t, "f", true); + case Tint64: return writeBasicType(t, target.c_longsize == 8 ? "l" : "x", true); + case Tuns64: return writeBasicType(t, target.c_longsize == 8 ? "m" : "y", true); + case Tint128: return writeBasicType(t, "n", true); + case Tuns128: return writeBasicType(t, "o", true); + case Tfloat64: return writeBasicType(t, "d", true); + case Tfloat80: return writeBasicType(t, "e", true); + case Tbool: return writeBasicType(t, "b", true); + case Tchar: return writeBasicType(t, "c", true); + case Twchar: return writeBasicType(t, "t", true); // unsigned short (perhaps use "Ds" ? + case Tdchar: return writeBasicType(t, "w", true); // wchar_t (UTF-32) (perhaps use "Di" ? + case Timaginary32: return writeBasicType(t, "Gf", false); // 'G' means imaginary + case Timaginary64: return writeBasicType(t, "Gd", false); + case Timaginary80: return writeBasicType(t, "Ge", false); + case Tcomplex32: return writeBasicType(t, "Cf", false); // 'C' means complex + case Tcomplex64: return writeBasicType(t, "Cd", false); + case Tcomplex80: return writeBasicType(t, "Ce", false); default: - // Handle any target-specific basic types. - if (auto tm = target.cppTypeMangle(t)) - { - // Only do substitution for mangles that are longer than 1 character. - if (tm[1] != 0 || t.isConst()) - { - if (substitute(t)) - return; - else - append(t); - } - CV_qualifiers(t); - buf.writestring(tm); - return; - } return error(t); } - writeBasicType(t, p, c); } override void visit(TypeVector t) @@ -1443,15 +1432,15 @@ extern(C++): const id = t.sym.ident; //printf("enum id = '%s'\n", id.toChars()); if (id == Id.__c_long) - return writeBasicType(t, 0, 'l'); + return writeBasicType(t, "l", true); else if (id == Id.__c_ulong) - return writeBasicType(t, 0, 'm'); + return writeBasicType(t, "m", true); else if (id == Id.__c_wchar_t) - return writeBasicType(t, 0, 'w'); + return writeBasicType(t, "w", true); else if (id == Id.__c_longlong) - return writeBasicType(t, 0, 'x'); + return writeBasicType(t, "x", true); else if (id == Id.__c_ulonglong) - return writeBasicType(t, 0, 'y'); + return writeBasicType(t, "y", true); doSymbol(t); } diff --git a/test/runnable/cppa.d b/test/runnable/cppa.d index 4f50b7376e40..9e75318c851c 100644 --- a/test/runnable/cppa.d +++ b/test/runnable/cppa.d @@ -727,6 +727,18 @@ void test16() static assert(0); } +/****************************************/ + +alias nullptr_t = typeof(null); + +extern (C++) void testnull(nullptr_t); +extern (C++) void testnullnull(nullptr_t, nullptr_t); + +void test17() +{ + testnull(null); + testnullnull(null, null); +} /****************************************/ @@ -1611,6 +1623,7 @@ void main() test13289(); test15(); test16(); + test17(); func13707(); func13932(S13932!(-1)(0)); foo13337(S13337()); diff --git a/test/runnable/extra-files/cppb.cpp b/test/runnable/extra-files/cppb.cpp index 550cd677d2dd..eacbca55fe08 100644 --- a/test/runnable/extra-files/cppb.cpp +++ b/test/runnable/extra-files/cppb.cpp @@ -466,6 +466,19 @@ unsigned long testul(unsigned long ul) /******************************************/ +void testnull(nullptr_t n) +{ + assert(n == NULL); +} + +void testnullnull(nullptr_t n1, nullptr_t n2) +{ + assert(n1 == NULL); + assert(n2 == NULL); +} + +/******************************************/ + struct S13707 { void* a;