Skip to content

Commit

Permalink
Handle virtual destructors in C++ classes
Browse files Browse the repository at this point in the history
This resolves crashing on virtual destructors if Clang is build with
assertions and corrects vtbl indices for tables with destructors.

Fixes #240.
  • Loading branch information
zeule committed Jun 25, 2021
1 parent be69d0b commit edb91fb
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 11 deletions.
49 changes: 38 additions & 11 deletions sources/libClangSharp/ClangSharp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4693,23 +4693,50 @@ CXCursor clangsharp_Cursor_getVBase(CXCursor C, unsigned i) {
return clang_getNullCursor();
}

int64_t clangsharp_Cursor_getVtblIdx(CXCursor C) {
namespace {
int64_t getVtblIdx(const GlobalDecl& d)
{
const CXXMethodDecl* CMD = static_cast<const CXXMethodDecl*>(d.getDecl());
if (VTableContextBase::hasVtableSlot(CMD)) {
VTableContextBase* VTC = CMD->getASTContext().getVTableContext();

if (MicrosoftVTableContext* MSVTC = dyn_cast<MicrosoftVTableContext>(VTC)) {
MethodVFTableLocation ML = MSVTC->getMethodVFTableLocation(d);
return ML.Index;
}

if (ItaniumVTableContext* IVTC = dyn_cast<ItaniumVTableContext>(VTC)) {
return IVTC->getMethodVTableIndex(d);
}
}

return -1;
}
}

int64_t clangsharp_Cursor_getDtorVtblIdx(CXCursor C, CX_DestructorType dtor)
{
if (isDeclOrTU(C.kind)) {
const Decl* D = getCursorDecl(C);

if (const CXXMethodDecl* CMD = dyn_cast<CXXMethodDecl>(D)) {
if (VTableContextBase::hasVtableSlot(CMD)) {
VTableContextBase* VTC = getASTUnit(getCursorTU(C))->getASTContext().getVTableContext();
if (const CXXDestructorDecl* CMD = dyn_cast<CXXDestructorDecl>(D)) {
return getVtblIdx(GlobalDecl(CMD, dtor));
}
}
return -1;
}

if (MicrosoftVTableContext* MSVTC = dyn_cast<MicrosoftVTableContext>(VTC)) {
MethodVFTableLocation ML = MSVTC->getMethodVFTableLocation(CMD);
return ML.Index;
}
int64_t clangsharp_Cursor_getVtblIdx(CXCursor C) {
if (isDeclOrTU(C.kind)) {
const Decl* D = getCursorDecl(C);

if (ItaniumVTableContext* IVTC = dyn_cast<ItaniumVTableContext>(VTC)) {
return IVTC->getMethodVTableIndex(CMD);
}
if (const CXXMethodDecl* CMD = dyn_cast<CXXMethodDecl>(D)) {
int64_t dtorIdx = clangsharp_Cursor_getDtorVtblIdx(C, Deleting);
if (dtorIdx != -1) {
return dtorIdx;
}

return getVtblIdx(CMD);
}
}

Expand Down
9 changes: 9 additions & 0 deletions sources/libClangSharp/ClangSharp.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,13 @@ enum CX_VariableCaptureKind {
CX_VCK_VLAType = clang::CapturedStmt::VCK_VLAType + 1
};

enum CX_DestructorType {
Deleting = clang::Dtor_Deleting,
Complete = clang::Dtor_Complete,
Base = clang::Dtor_Base,
Comdat = clang::Dtor_Comdat
};

struct CX_TemplateArgument {
CXTemplateArgumentKind kind;
int xdata;
Expand Down Expand Up @@ -722,6 +729,8 @@ CLANGSHARP_LINKAGE CXCursor clangsharp_Cursor_getUsedContext(CXCursor C);

CLANGSHARP_LINKAGE CXCursor clangsharp_Cursor_getVBase(CXCursor C, unsigned i);

CLANGSHARP_LINKAGE int64_t clangsharp_Cursor_getDtorVtblIdx(CXCursor C, CX_DestructorType dtor);

CLANGSHARP_LINKAGE int64_t clangsharp_Cursor_getVtblIdx(CXCursor C);

CLANGSHARP_LINKAGE void clangsharp_TemplateArgument_dispose(CX_TemplateArgument T);
Expand Down

0 comments on commit edb91fb

Please sign in to comment.