Skip to content

Commit

Permalink
Differentiate C++ catch clauses from D ones by wrapping std::type_inf…
Browse files Browse the repository at this point in the history
…o 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.
  • Loading branch information
Syniurge authored and kinke committed Feb 24, 2018
1 parent a5aa8b2 commit 0afba53
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 3 deletions.
24 changes: 23 additions & 1 deletion gen/trycatchfinally.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"

////////////////////////////////////////////////////////////////////////////////

Expand Down Expand Up @@ -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<llvm::StructType>(
static_cast<IrTypeClass*>(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();
}
Expand Down
2 changes: 1 addition & 1 deletion runtime/druntime
Submodule druntime updated 1 files
+4 −25 src/rt/dwarfeh.d
2 changes: 1 addition & 1 deletion tests/d2/dmd-testsuite
Submodule dmd-testsuite updated 1 files
+8 −1 runnable/cppa.d

0 comments on commit 0afba53

Please sign in to comment.