Skip to content

Commit c31a508

Browse files
authored
Handle virtual destructors in C++ classes (#243)
This resolves crashing on virtual destructors if Clang is build with assertions and corrects vtbl indices for tables with destructors. Fixes #240.
1 parent a4e94b5 commit c31a508

File tree

4 files changed

+71
-11
lines changed

4 files changed

+71
-11
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright (c) Microsoft and Contributors. All rights reserved. Licensed under the University of Illinois/NCSA Open Source License. See LICENSE.txt in the project root for license information.
2+
// Ported from https://github.com/microsoft/ClangSharp/blob/main/sources/libClangSharp
3+
4+
namespace ClangSharp.Interop
5+
{
6+
public enum CX_DestructorType
7+
{
8+
Deleting,
9+
Complete,
10+
Base,
11+
Comdat
12+
}
13+
}

sources/ClangSharp.Interop/clangsharp.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -865,6 +865,10 @@ public static partial class clangsharp
865865
[DllImport("libClangSharp", CallingConvention = CallingConvention.Cdecl, EntryPoint = "clangsharp_Cursor_getVBase", ExactSpelling = true)]
866866
public static extern CXCursor Cursor_getVBase(CXCursor C, [NativeTypeName("unsigned int")] uint i);
867867

868+
[DllImport("libClangSharp", CallingConvention = CallingConvention.Cdecl, EntryPoint = "clangsharp_Cursor_getDtorVtblIdx", ExactSpelling = true)]
869+
[return: NativeTypeName("int64_t")]
870+
public static extern long Cursor_getDtorVtblIdx(CXCursor C, CX_DestructorType dtor);
871+
868872
[DllImport("libClangSharp", CallingConvention = CallingConvention.Cdecl, EntryPoint = "clangsharp_Cursor_getVtblIdx", ExactSpelling = true)]
869873
[return: NativeTypeName("int64_t")]
870874
public static extern long Cursor_getVtblIdx(CXCursor C);

sources/libClangSharp/ClangSharp.cpp

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,16 @@
88
#include "CXTranslationUnit.h"
99
#include "CXType.h"
1010

11+
#ifdef _MSC_VER
1112
#pragma warning(push)
1213
#pragma warning(disable : 4146 4244 4267 4291 4624 4996)
14+
#endif
1315

1416
#include <clang/Basic/SourceManager.h>
1517

18+
#ifdef _MSC_VER
1619
#pragma warning(pop)
20+
#endif
1721

1822
using namespace clang;
1923
using namespace clang::cxcursor;
@@ -61,6 +65,25 @@ bool isStmtOrExpr(CXCursorKind kind) {
6165
return clang_isStatement(kind) || clang_isExpression(kind);
6266
}
6367

68+
int64_t getVtblIdx(const GlobalDecl& d)
69+
{
70+
const CXXMethodDecl* CMD = static_cast<const CXXMethodDecl*>(d.getDecl());
71+
if (VTableContextBase::hasVtableSlot(CMD)) {
72+
VTableContextBase* VTC = CMD->getASTContext().getVTableContext();
73+
74+
if (MicrosoftVTableContext* MSVTC = dyn_cast<MicrosoftVTableContext>(VTC)) {
75+
MethodVFTableLocation ML = MSVTC->getMethodVFTableLocation(d);
76+
return ML.Index;
77+
}
78+
79+
if (ItaniumVTableContext* IVTC = dyn_cast<ItaniumVTableContext>(VTC)) {
80+
return IVTC->getMethodVTableIndex(d);
81+
}
82+
}
83+
84+
return -1;
85+
}
86+
6487
CXCursor clangsharp_Cursor_getArgument(CXCursor C, unsigned i) {
6588
if (isDeclOrTU(C.kind)) {
6689
const Decl* D = getCursorDecl(C);
@@ -4693,23 +4716,30 @@ CXCursor clangsharp_Cursor_getVBase(CXCursor C, unsigned i) {
46934716
return clang_getNullCursor();
46944717
}
46954718

4696-
int64_t clangsharp_Cursor_getVtblIdx(CXCursor C) {
4719+
int64_t clangsharp_Cursor_getDtorVtblIdx(CXCursor C, CX_DestructorType dtor)
4720+
{
46974721
if (isDeclOrTU(C.kind)) {
46984722
const Decl* D = getCursorDecl(C);
46994723

4700-
if (const CXXMethodDecl* CMD = dyn_cast<CXXMethodDecl>(D)) {
4701-
if (VTableContextBase::hasVtableSlot(CMD)) {
4702-
VTableContextBase* VTC = getASTUnit(getCursorTU(C))->getASTContext().getVTableContext();
4724+
if (const CXXDestructorDecl* CMD = dyn_cast<CXXDestructorDecl>(D)) {
4725+
return getVtblIdx(GlobalDecl(CMD, static_cast<CXXDtorType>(dtor)));
4726+
}
4727+
}
4728+
return -1;
4729+
}
47034730

4704-
if (MicrosoftVTableContext* MSVTC = dyn_cast<MicrosoftVTableContext>(VTC)) {
4705-
MethodVFTableLocation ML = MSVTC->getMethodVFTableLocation(CMD);
4706-
return ML.Index;
4707-
}
4731+
int64_t clangsharp_Cursor_getVtblIdx(CXCursor C) {
4732+
if (isDeclOrTU(C.kind)) {
4733+
const Decl* D = getCursorDecl(C);
47084734

4709-
if (ItaniumVTableContext* IVTC = dyn_cast<ItaniumVTableContext>(VTC)) {
4710-
return IVTC->getMethodVTableIndex(CMD);
4711-
}
4735+
if (const CXXMethodDecl* CMD = dyn_cast<CXXMethodDecl>(D)) {
4736+
int64_t dtorIdx = clangsharp_Cursor_getDtorVtblIdx(C, Deleting); // will test if CMD is a dtor
4737+
if (dtorIdx != -1) { // yes, it is a dtor
4738+
return dtorIdx;
47124739
}
4740+
4741+
// no, it is a regular method
4742+
return getVtblIdx(CMD);
47134743
}
47144744
}
47154745

sources/libClangSharp/ClangSharp.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
#ifndef LIBCLANGSHARP_CLANGSHARP_H
44
#define LIBCLANGSHARP_CLANGSHARP_H
55

6+
#ifdef _MSC_VER
67
#pragma warning(push)
78
#pragma warning(disable : 4146 4244 4267 4291 4624 4996)
9+
#endif
810

911
#include <clang/AST/Decl.h>
1012
#include <clang/AST/DeclCXX.h>
@@ -19,7 +21,9 @@
1921
#include <clang/Basic/Specifiers.h>
2022
#include <clang-c/Index.h>
2123

24+
#ifdef _MSC_VER
2225
#pragma warning(pop)
26+
#endif
2327

2428
#ifdef __cplusplus
2529
#define EXTERN_C extern "C"
@@ -202,6 +206,13 @@ enum CX_VariableCaptureKind {
202206
CX_VCK_VLAType = clang::CapturedStmt::VCK_VLAType + 1
203207
};
204208

209+
enum CX_DestructorType {
210+
Deleting = clang::Dtor_Deleting,
211+
Complete = clang::Dtor_Complete,
212+
Base = clang::Dtor_Base,
213+
Comdat = clang::Dtor_Comdat
214+
};
215+
205216
struct CX_TemplateArgument {
206217
CXTemplateArgumentKind kind;
207218
int xdata;
@@ -722,6 +733,8 @@ CLANGSHARP_LINKAGE CXCursor clangsharp_Cursor_getUsedContext(CXCursor C);
722733

723734
CLANGSHARP_LINKAGE CXCursor clangsharp_Cursor_getVBase(CXCursor C, unsigned i);
724735

736+
CLANGSHARP_LINKAGE int64_t clangsharp_Cursor_getDtorVtblIdx(CXCursor C, CX_DestructorType dtor);
737+
725738
CLANGSHARP_LINKAGE int64_t clangsharp_Cursor_getVtblIdx(CXCursor C);
726739

727740
CLANGSHARP_LINKAGE void clangsharp_TemplateArgument_dispose(CX_TemplateArgument T);

0 commit comments

Comments
 (0)