From a46cf3a0d3b07a7ad6723d3c219ed56a530ff354 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sat, 8 Jul 2023 22:04:55 +0200 Subject: [PATCH] Add virtual destructor --- autotest/autotest.bat | 3 ++ autotest/virtualdestruct.cpp | 63 ++++++++++++++++++++++++++++++++++++ oscar64/Ident.cpp | 8 +++++ oscar64/Ident.h | 1 + oscar64/Parser.cpp | 50 ++++++++++++++++++++++++++-- 5 files changed, 122 insertions(+), 3 deletions(-) create mode 100644 autotest/virtualdestruct.cpp diff --git a/autotest/autotest.bat b/autotest/autotest.bat index f6aca82..48958b2 100644 --- a/autotest/autotest.bat +++ b/autotest/autotest.bat @@ -1,5 +1,8 @@ rem @echo off +@call :test virtualdestruct.cpp +@if %errorlevel% neq 0 goto :error + @call :test vcalltest.cpp @if %errorlevel% neq 0 goto :error diff --git a/autotest/virtualdestruct.cpp b/autotest/virtualdestruct.cpp new file mode 100644 index 0000000..a9bd394 --- /dev/null +++ b/autotest/virtualdestruct.cpp @@ -0,0 +1,63 @@ +#include + +int a, b, c; + +struct A +{ + A(void) + { + a++; + } + + virtual ~A(void) + { + a--; + } +}; + +struct B : A +{ + B(void) + { + b++; + } + + virtual ~B(void) + { + b--; + } +}; + + +struct C : B +{ + C(void) + { + c++; + } + + virtual ~C(void) + { + c--; + } +}; + + +int main() +{ + A * t[3]; + + t[0] = new A(); + t[1] = new B(); + t[2] = new C(); + + assert(a == 3 && b == 2 && c == 1); + + delete t[0]; + delete t[1]; + delete t[2]; + + assert(a == 0 && b == 0 && c == 0); + + return 0; +} diff --git a/oscar64/Ident.cpp b/oscar64/Ident.cpp index daabd53..29e89f6 100644 --- a/oscar64/Ident.cpp +++ b/oscar64/Ident.cpp @@ -45,6 +45,14 @@ const Ident* Ident::Unique(const char* str) } +const Ident* Ident::PreMangle(const char* str) const +{ + char buffer[100]; + strcpy_s(buffer, str); + strcat_s(buffer, mString); + return Unique(buffer); +} + const Ident* Ident::Mangle(const char* str) const { char buffer[100]; diff --git a/oscar64/Ident.h b/oscar64/Ident.h index 661c83c..de44870 100644 --- a/oscar64/Ident.h +++ b/oscar64/Ident.h @@ -10,6 +10,7 @@ public: static const Ident* Unique(const char* str); const Ident* Mangle(const char* str) const; + const Ident* PreMangle(const char* str) const; protected: Ident(const char* str, unsigned int hash); }; diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index dcedd38..e0e6013 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -307,11 +307,26 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) if (mdec->mBase->mFlags & DTF_VIRTUAL) { Declaration* vpdec = vdec; - Declaration* vmdec = vpdec->mScope->Lookup(ident); - while (!vmdec && vpdec->mBase) + Declaration* vmdec; + if (mdec->mIdent->mString[0] == '~') + { + // this is the destructor, need special search + + vmdec = vpdec->mScope->Lookup(vpdec->mIdent->PreMangle("~")); + while (!vmdec && vpdec->mBase) + { + vpdec = vpdec->mBase; + vmdec = vpdec->mScope->Lookup(vpdec->mIdent->PreMangle("~")); + } + } + else { - vpdec = vpdec->mBase; vmdec = vpdec->mScope->Lookup(ident); + while (!vmdec && vpdec->mBase) + { + vpdec = vpdec->mBase; + vmdec = vpdec->mScope->Lookup(ident); + } } Declaration* vmpdec = nullptr; @@ -2585,6 +2600,31 @@ void Parser::AppendMemberDestructor(Declaration* pthis) dec = dec->mPrev; } } + + Declaration* bcdec = pthis->mBase->mBase; + while (bcdec) + { + if (bcdec->mBase->mDestructor) + { + Declaration* mdec = bcdec->mBase->mDestructor; + + Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); + cexp->mDecValue = mdec; + cexp->mDecType = cexp->mDecValue->mBase; + + Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = pthisexp; + + Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); + + sexp->mLeft = pthis->mBase->mDestructor->mValue; + sexp->mRight = dexp; + pthis->mBase->mDestructor->mValue = sexp; + } + + bcdec = bcdec->mNext; + } } } } @@ -3018,6 +3058,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex cdec->mBase = ctdec; cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); + ctdec->mFlags |= storageFlags & DTF_VIRTUAL; cdec->mSection = mCodeSection; cdec->mBase->mFlags |= typeFlags; @@ -4904,6 +4945,9 @@ Expression* Parser::ParsePrefixExpression(bool lhs) dexp->mLeft = cexp; dexp->mRight = pexp; + if (cexp->mDecValue->mBase->mFlags & DTF_VIRTUAL) + dexp->mType = EX_VCALL; + Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); sexp->mLeft = iexp; sexp->mRight = new Expression(mScanner->mLocation, EX_IF);