Add virtual destructor
This commit is contained in:
parent
ed9aa3503b
commit
a46cf3a0d3
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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];
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue