mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-16 04:43:14 +01:00
Fix #239.
This commit is contained in:
33
gen/toir.cpp
33
gen/toir.cpp
@@ -1104,14 +1104,32 @@ DValue* DotVarExp::toElem(IRState* p)
|
||||
LLValue* vthis = l->getRVal();
|
||||
if (!vthis2) vthis2 = vthis;
|
||||
|
||||
// super call
|
||||
if (e1->op == TOKsuper) {
|
||||
//
|
||||
// decide whether this function needs to be looked up in the vtable
|
||||
//
|
||||
bool vtbllookup = fdecl->isAbstract() || (!fdecl->isFinal() && fdecl->isVirtual());
|
||||
|
||||
// even virtual functions are looked up directly if super or DotTypeExp
|
||||
// are used, thus we need to walk through the this expression and check
|
||||
Expression* e = e1;
|
||||
while (e && vtbllookup) {
|
||||
if (e->op == TOKsuper || e->op == TOKdottype)
|
||||
vtbllookup = false;
|
||||
else if (e->op == TOKcast)
|
||||
e = ((CastExp*)e)->e1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// look up function
|
||||
//
|
||||
if (!vtbllookup) {
|
||||
DtoForceDeclareDsymbol(fdecl);
|
||||
funcval = fdecl->ir.irFunc->func;
|
||||
assert(funcval);
|
||||
}
|
||||
// normal virtual call
|
||||
else if (fdecl->isAbstract() || (!fdecl->isFinal() && fdecl->isVirtual())) {
|
||||
else {
|
||||
assert(fdecl->vtblIndex > 0);
|
||||
assert(e1type->ty == Tclass);
|
||||
|
||||
@@ -1131,12 +1149,7 @@ DValue* DotVarExp::toElem(IRState* p)
|
||||
if (Logger::enabled())
|
||||
Logger::cout() << "funcval casted: " << *funcval << '\n';
|
||||
}
|
||||
// static call
|
||||
else {
|
||||
DtoForceDeclareDsymbol(fdecl);
|
||||
funcval = fdecl->ir.irFunc->func;
|
||||
assert(funcval);
|
||||
}
|
||||
|
||||
return new DFuncValue(fdecl, funcval, vthis2);
|
||||
}
|
||||
else {
|
||||
|
||||
28
tests/mini/classes13_bug239.d
Normal file
28
tests/mini/classes13_bug239.d
Normal file
@@ -0,0 +1,28 @@
|
||||
extern(C) int printf(char*, ...);
|
||||
|
||||
class A {
|
||||
bool Afoo = false;
|
||||
void foo() { Afoo = true; }
|
||||
}
|
||||
|
||||
class B : A {}
|
||||
|
||||
class C : B {
|
||||
bool Cfoo = false;
|
||||
void foo() { Cfoo = true; }
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
scope c1 = new C();
|
||||
c1.foo();
|
||||
assert(c1.Cfoo && !c1.Afoo);
|
||||
|
||||
scope c2 = new C();
|
||||
c2.B.foo();
|
||||
assert(!c2.Cfoo && c2.Afoo);
|
||||
|
||||
scope c3 = new C();
|
||||
c3.A.foo();
|
||||
assert(!c3.Cfoo && c3.Afoo);
|
||||
}
|
||||
Reference in New Issue
Block a user