Add virtual destructor

This commit is contained in:
drmortalwombat 2023-07-08 22:04:55 +02:00
parent ed9aa3503b
commit a46cf3a0d3
5 changed files with 122 additions and 3 deletions

View File

@ -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

View File

@ -0,0 +1,63 @@
#include <assert.h>
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;
}

View File

@ -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];

View File

@ -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);
};

View File

@ -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);