diff --git a/CfrontCodeGenerator.cpp b/CfrontCodeGenerator.cpp index b7e32020..82244d34 100644 --- a/CfrontCodeGenerator.cpp +++ b/CfrontCodeGenerator.cpp @@ -664,14 +664,22 @@ void CfrontCodeGenerator::InsertCXXMethodDecl(const CXXMethodDecl* stmt, SkipBod } else if(const auto* dtor = dyn_cast_or_null(stmt)) { // Based on: https://www.dre.vanderbilt.edu/~schmidt/PDF/C++-translation.pdf + if(not HasDtor(GetRecordDeclType(dtor->getParent()))) { + return; + } + InsertVtblPtr(stmt, stmt->getParent(), bodyStmts); - if(body) { - bodyStmts.AddBodyStmts(body); + for(const auto& base : llvm::reverse(dtor->getParent()->bases())) { + if(not dtor->isVirtual()) { + continue; + } + + InsertVtblPtr(stmt, dyn_cast_or_null(base.getType()->getAsRecordDecl()), bodyStmts); } - if(not HasDtor(GetRecordDeclType(dtor->getParent()))) { - return; + if(body) { + bodyStmts.AddBodyStmts(body); } for(const auto& base : llvm::reverse(dtor->getParent()->bases())) { diff --git a/tests/EduCfrontTest22.cpp b/tests/EduCfrontTest22.cpp index 3951f916..6a52a2c0 100644 --- a/tests/EduCfrontTest22.cpp +++ b/tests/EduCfrontTest22.cpp @@ -25,8 +25,20 @@ class Apple : public Fruit { void Print() const override { puts("Apple"); } }; +class Orange : public Apple { +public: + Orange() + : Apple{} + {} + + virtual ~Orange() override { Print(); } + + void Print() const override { puts("Orange"); } +}; + + int main() { - Apple x{}; + Orange x{}; } diff --git a/tests/EduCfrontTest22.expect b/tests/EduCfrontTest22.expect index 38ba99f1..d420cb1d 100644 --- a/tests/EduCfrontTest22.expect +++ b/tests/EduCfrontTest22.expect @@ -56,6 +56,7 @@ inline Apple * Constructor_Apple(Apple * __this) inline void Destructor_Apple(Apple * __this) { + __this->__vptrFruit = __vtbl_array[1]; (*((void (*)(const Apple *))((__this)->__vptrFruit[1]).f))((((const Apple *)(char *)(__this)) + ((__this)->__vptrFruit[1]).d)); Destructor_Fruit((Fruit *)__this); } @@ -66,12 +67,37 @@ inline void PrintApple(const Apple * __this) } +typedef struct Orange +{ + __mptr * __vptrFruit; +} Orange; + +inline Orange * Constructor_Orange(Orange * __this) +{ + Constructor_Apple((Apple *)__this); + __this->__vptrFruit = __vtbl_array[2]; + return __this; +} + +inline void Destructor_Orange(Orange * __this) +{ + __this->__vptrFruit = __vtbl_array[2]; + (*((void (*)(const Orange *))((__this)->__vptrFruit[1]).f))((((const Orange *)(char *)(__this)) + ((__this)->__vptrFruit[1]).d)); + Destructor_Apple((Apple *)__this); +} + +inline void PrintOrange(const Orange * __this) +{ + puts("Orange"); +} + + int __main(void) { - Apple x; - Constructor_Apple((Apple *)&x); + Orange x; + Constructor_Orange((Orange *)&x); return 0; - (*((void (*)(Apple *))((&x)->__vptrFruit[0]).f))((((Apple *)(char *)(&x)) + ((&x)->__vptrFruit[0]).d)); + (*((void (*)(Orange *))((&x)->__vptrFruit[0]).f))((((Orange *)(char *)(&x)) + ((&x)->__vptrFruit[0]).d)); } int main(void) @@ -85,8 +111,9 @@ int main(void) __mptr __vtbl_Fruit[2] = {{0, 0, (__vptp)Destructor_Fruit}, {0, 0, (__vptp)PrintFruit}}; __mptr __vtbl_Apple[2] = {{0, 0, (__vptp)Destructor_Apple}, {0, 0, (__vptp)PrintApple}}; +__mptr __vtbl_Orange[2] = {{0, 0, (__vptp)Destructor_Orange}, {0, 0, (__vptp)PrintOrange}}; -__mptr * __vtbl_array[2] = {__vtbl_Fruit, __vtbl_Apple}; +__mptr * __vtbl_array[3] = {__vtbl_Fruit, __vtbl_Apple, __vtbl_Orange}; void __cxa_start(void) { diff --git a/tests/EduCfrontTest5.expect b/tests/EduCfrontTest5.expect index 18637da9..7f69b907 100644 --- a/tests/EduCfrontTest5.expect +++ b/tests/EduCfrontTest5.expect @@ -92,6 +92,8 @@ typedef struct Derived inline void Destructor_Derived(Derived * __this) { + __this->__vptrBaseSecond = __vtbl_array[3]; + __this->__vptrBase = __vtbl_array[2]; __this->mD = 7; Destructor_BaseSecond((BaseSecond *)__this); Destructor_Base((Base *)__this); diff --git a/tests/EduCfrontTest7.expect b/tests/EduCfrontTest7.expect index 78e9233d..a828fce2 100644 --- a/tests/EduCfrontTest7.expect +++ b/tests/EduCfrontTest7.expect @@ -68,6 +68,7 @@ typedef struct BaseSecond inline void Destructor_BaseSecond(BaseSecond * __this) { + __this->__vptrBase = __vtbl_array[1]; Destructor_Base((Base *)__this); } @@ -113,6 +114,8 @@ typedef struct Derived inline void Destructor_Derived(Derived * __this) { + __this->__vptrBaseThird = __vtbl_array[4]; + __this->__vptrBase = __vtbl_array[3]; __this->mD = 7; Destructor_BaseThird((BaseThird *)__this); Destructor_BaseSecond((BaseSecond *)__this); diff --git a/tests/EduCfrontVtable4Test.expect b/tests/EduCfrontVtable4Test.expect index bc77d84d..6c14bb03 100644 --- a/tests/EduCfrontVtable4Test.expect +++ b/tests/EduCfrontVtable4Test.expect @@ -60,6 +60,7 @@ inline void OtherB(B * __this) inline void Destructor_B(B * __this) { + __this->__vptrA = __vtbl_array[1]; Destructor_A((A *)__this); } @@ -91,6 +92,7 @@ inline void OtherC(C * __this) inline void Destructor_C(C * __this) { + __this->__vptrA = __vtbl_array[2]; Destructor_B((B *)__this); } diff --git a/tests/EduCfrontVtable5Test.expect b/tests/EduCfrontVtable5Test.expect index 76e689cc..82c28912 100644 --- a/tests/EduCfrontVtable5Test.expect +++ b/tests/EduCfrontVtable5Test.expect @@ -43,6 +43,7 @@ typedef struct Derived inline void Destructor_Derived(Derived * __this) { + __this->__vptrBase = __vtbl_array[1]; puts("~Derived"); Destructor_Base((Base *)__this); } diff --git a/tests/EduCfrontVtable7Test.expect b/tests/EduCfrontVtable7Test.expect index 47457157..1ab34ce4 100644 --- a/tests/EduCfrontVtable7Test.expect +++ b/tests/EduCfrontVtable7Test.expect @@ -56,6 +56,7 @@ inline void FunApple(Apple * __this) inline void Destructor_Apple(Apple * __this) { + __this->__vptrFruit = __vtbl_array[1]; Destructor_Fruit((Fruit *)__this); } @@ -83,6 +84,7 @@ inline void FunPinkLady(PinkLady * __this) inline void Destructor_PinkLady(PinkLady * __this) { + __this->__vptrFruit = __vtbl_array[2]; Destructor_Apple((Apple *)__this); } diff --git a/tests/Issue701.expect b/tests/Issue701.expect index e9374b7a..315ac528 100644 --- a/tests/Issue701.expect +++ b/tests/Issue701.expect @@ -57,6 +57,7 @@ inline void PrintApple(Apple * __this) inline void Destructor_Apple(Apple * __this) { + __this->__vptrFruit = __vtbl_array[1]; Destructor_Fruit((Fruit *)__this); } @@ -84,6 +85,7 @@ inline void PrintPinkLady(PinkLady * __this) inline void Destructor_PinkLady(PinkLady * __this) { + __this->__vptrFruit = __vtbl_array[2]; Destructor_Apple((Apple *)__this); }