Add virtual destructor
This commit is contained in:
parent
ed9aa3503b
commit
a46cf3a0d3
|
@ -1,5 +1,8 @@
|
||||||
rem @echo off
|
rem @echo off
|
||||||
|
|
||||||
|
@call :test virtualdestruct.cpp
|
||||||
|
@if %errorlevel% neq 0 goto :error
|
||||||
|
|
||||||
@call :test vcalltest.cpp
|
@call :test vcalltest.cpp
|
||||||
@if %errorlevel% neq 0 goto :error
|
@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
|
const Ident* Ident::Mangle(const char* str) const
|
||||||
{
|
{
|
||||||
char buffer[100];
|
char buffer[100];
|
||||||
|
|
|
@ -10,6 +10,7 @@ public:
|
||||||
|
|
||||||
static const Ident* Unique(const char* str);
|
static const Ident* Unique(const char* str);
|
||||||
const Ident* Mangle(const char* str) const;
|
const Ident* Mangle(const char* str) const;
|
||||||
|
const Ident* PreMangle(const char* str) const;
|
||||||
protected:
|
protected:
|
||||||
Ident(const char* str, unsigned int hash);
|
Ident(const char* str, unsigned int hash);
|
||||||
};
|
};
|
||||||
|
|
|
@ -307,12 +307,27 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt)
|
||||||
if (mdec->mBase->mFlags & DTF_VIRTUAL)
|
if (mdec->mBase->mFlags & DTF_VIRTUAL)
|
||||||
{
|
{
|
||||||
Declaration* vpdec = vdec;
|
Declaration* vpdec = vdec;
|
||||||
Declaration* vmdec = vpdec->mScope->Lookup(ident);
|
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
|
||||||
|
{
|
||||||
|
vmdec = vpdec->mScope->Lookup(ident);
|
||||||
while (!vmdec && vpdec->mBase)
|
while (!vmdec && vpdec->mBase)
|
||||||
{
|
{
|
||||||
vpdec = vpdec->mBase;
|
vpdec = vpdec->mBase;
|
||||||
vmdec = vpdec->mScope->Lookup(ident);
|
vmdec = vpdec->mScope->Lookup(ident);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Declaration* vmpdec = nullptr;
|
Declaration* vmpdec = nullptr;
|
||||||
|
|
||||||
|
@ -2585,6 +2600,31 @@ void Parser::AppendMemberDestructor(Declaration* pthis)
|
||||||
dec = dec->mPrev;
|
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->mBase = ctdec;
|
||||||
|
|
||||||
cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE);
|
cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE);
|
||||||
|
ctdec->mFlags |= storageFlags & DTF_VIRTUAL;
|
||||||
|
|
||||||
cdec->mSection = mCodeSection;
|
cdec->mSection = mCodeSection;
|
||||||
cdec->mBase->mFlags |= typeFlags;
|
cdec->mBase->mFlags |= typeFlags;
|
||||||
|
@ -4904,6 +4945,9 @@ Expression* Parser::ParsePrefixExpression(bool lhs)
|
||||||
dexp->mLeft = cexp;
|
dexp->mLeft = cexp;
|
||||||
dexp->mRight = pexp;
|
dexp->mRight = pexp;
|
||||||
|
|
||||||
|
if (cexp->mDecValue->mBase->mFlags & DTF_VIRTUAL)
|
||||||
|
dexp->mType = EX_VCALL;
|
||||||
|
|
||||||
Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE);
|
Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE);
|
||||||
sexp->mLeft = iexp;
|
sexp->mLeft = iexp;
|
||||||
sexp->mRight = new Expression(mScanner->mLocation, EX_IF);
|
sexp->mRight = new Expression(mScanner->mLocation, EX_IF);
|
||||||
|
|
Loading…
Reference in New Issue