From 0afba530dc62849e0d19972c6bf8f7ececaeefff Mon Sep 17 00:00:00 2001 From: Elie Morisse Date: Tue, 20 Feb 2018 21:06:36 -0300 Subject: [PATCH] Differentiate C++ catch clauses from D ones by wrapping std::type_info pointers inside __cpp_type_info_ptr class instances like DMD does. Previously assuming in the personality routine that encountering a C++ exception meant that catch clauses were raw std::type_info pointers was wrong in cases like: try { throwStdException(); // external C++ function throwing a std::exception } catch (Throwable t) { (...) } Generated __cpp_type_info_ptr constants receive the same mangling that they do within DMD. --- gen/trycatchfinally.cpp | 24 +++++++++++++++++++++++- runtime/druntime | 2 +- tests/d2/dmd-testsuite | 2 +- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/gen/trycatchfinally.cpp b/gen/trycatchfinally.cpp index de0380e7049..6efc8ff3302 100644 --- a/gen/trycatchfinally.cpp +++ b/gen/trycatchfinally.cpp @@ -14,10 +14,13 @@ #include "gen/classes.h" #include "gen/funcgenstate.h" #include "gen/llvmhelpers.h" +#include "gen/mangling.h" #include "gen/ms-cxx-helper.h" +#include "gen/rttibuilder.h" #include "gen/runtime.h" #include "gen/tollvm.h" #include "ir/irfunction.h" +#include "ir/irtypeclass.h" //////////////////////////////////////////////////////////////////////////////// @@ -159,9 +162,28 @@ void TryCatchScope::emitCatchBodies(IRState &irs, llvm::Value *ehPtrSlot) { LLGlobalVariable *ci; if (p.cd->isCPPclass()) { const char *name = Target::cppTypeInfoMangle(p.cd); - ci = getOrCreateGlobal( + auto cpp_ti = getOrCreateGlobal( p.cd->loc, irs.module, getVoidPtrType(), /*isConstant=*/true, LLGlobalValue::ExternalLinkage, /*init=*/nullptr, name); + + // Wrap std::type_info pointers inside a __cpp_type_info_ptr class instance so that + // the personality routine may differentiate C++ catch clauses from D ones. + OutBuffer mangleBuf; + mangleBuf.writestring("_D"); + mangleToBuffer(p.cd, &mangleBuf); + mangleBuf.printf("%d%s", 18, "_cpp_type_info_ptr"); + const auto wrapperMangle = getIRMangledVarName(mangleBuf.peekString(), LINKd); + + RTTIBuilder b(ClassDeclaration::cpp_type_info_ptr); + b.push(cpp_ti); + + auto wrapperType = llvm::cast( + static_cast(ClassDeclaration::cpp_type_info_ptr->type->ctype)->getMemoryLLType()); + auto wrapperInit = b.get_constant(wrapperType); + + ci = getOrCreateGlobal( + p.cd->loc, irs.module, wrapperType, /*isConstant=*/true, + LLGlobalValue::LinkOnceODRLinkage, wrapperInit, wrapperMangle); } else { ci = getIrAggr(p.cd)->getClassInfoSymbol(); } diff --git a/runtime/druntime b/runtime/druntime index c28b38c0920..c7384ca4df4 160000 --- a/runtime/druntime +++ b/runtime/druntime @@ -1 +1 @@ -Subproject commit c28b38c0920946c9fba3b1065cf4f9bb593b44af +Subproject commit c7384ca4df49644b284310a27a50b7fb655b4811 diff --git a/tests/d2/dmd-testsuite b/tests/d2/dmd-testsuite index f27297230ca..b42c107d2fe 160000 --- a/tests/d2/dmd-testsuite +++ b/tests/d2/dmd-testsuite @@ -1 +1 @@ -Subproject commit f27297230cacbfda24fecc28137ef8b14fc1d98b +Subproject commit b42c107d2fe856eee0739859ed84adeca93599ac