From b472d0bf80bec6764e4037fab36ee79f87ad970f 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 | 41 +++++++++++++++++++++++++++--- src/dmd/target.d | 13 ++++++++++ test/runnable/cppa.d | 14 ++++++++++ test/runnable/extra-files/cppb.cpp | 14 ++++++++++ 4 files changed, 79 insertions(+), 3 deletions(-) diff --git a/src/dmd/cppmangle.d b/src/dmd/cppmangle.d index 90ef08b2320e..7d275b6e3773 100644 --- a/src/dmd/cppmangle.d +++ b/src/dmd/cppmangle.d @@ -315,6 +315,40 @@ private final class CppMangleVisitor : Visitor !getQualifier(s)); // at global level } + /************************ + * Determine if type is a C++ fundamental type. + * Params: + * t = type to check + * Returns: + * true if it is a fundamental type + */ + static bool isFundamentalType(Type t) + { + // First check the target whether some specific ABI is being followed. + bool isFundamental = void; + if (target.cppFundamentalType(t, isFundamental)) + return isFundamental; + + // Peel off enum type from special types. + if (auto te = t.isTypeEnum()) + { + if (te.isSpecial()) + t = te.memType(); + } + + // Fundamental arithmetic types: + // 1. integral types: bool, char, int, ... + // 2. floating point types: float, double, real + // 3. void + // 4. null pointer: std::nullptr_t (since C++11) + if (t.ty == Tvoid || t.ty == Tbool) + return true; + else if (t.ty == Tnull && global.params.cplusplus >= CppStdRevision.cpp11) + return true; + else + return t.isTypeBasic() && (t.isintegral() || t.isreal()); + } + /****************************** * Write the mangled representation of a template argument. * Params: @@ -1090,7 +1124,8 @@ private final class CppMangleVisitor : Visitor */ void writeBasicType(Type t, char p, char c) { - if (p || t.isConst()) + // Only do substitutions for non-fundamental types. + if (!isFundamentalType(t) || t.isConst()) { if (substitute(t)) return; @@ -1296,8 +1331,8 @@ extern(C++): // 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()) + // Only do substitutions for non-fundamental types. + if (!isFundamentalType(t) || t.isConst()) { if (substitute(t)) return; diff --git a/src/dmd/target.d b/src/dmd/target.d index fb67a9632ca8..270858bb5362 100644 --- a/src/dmd/target.d +++ b/src/dmd/target.d @@ -502,6 +502,19 @@ struct Target return t; } + /** + * Checks whether type is a vendor-specific fundamental type. + * Params: + * t = type to inspect + * isFundamental = where to store result + * Returns: + * true if isFundamental was set by function + */ + extern (C++) bool cppFundamentalType(const Type t, ref bool isFundamental) + { + return false; + } + /** * Default system linkage for the target. * Returns: diff --git a/test/runnable/cppa.d b/test/runnable/cppa.d index 4f50b7376e40..01de4b97dac8 100644 --- a/test/runnable/cppa.d +++ b/test/runnable/cppa.d @@ -727,6 +727,19 @@ void test16() static assert(0); } +/****************************************/ +/+ FIXME: Requires C++11 compiler. +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 +1624,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..81b2b13c5498 100644 --- a/test/runnable/extra-files/cppb.cpp +++ b/test/runnable/extra-files/cppb.cpp @@ -464,6 +464,20 @@ unsigned long testul(unsigned long ul) return ul + sizeof(unsigned long); } +/******************************************/ +/* FIXME: Requires C++11 compiler. +void testnull(nullptr_t n) +{ + assert(n == NULL); +} + +void testnullnull(nullptr_t n1, nullptr_t n2) +{ + assert(n1 == NULL); + assert(n2 == NULL); +} +*/ + /******************************************/ struct S13707