# HG changeset patch # User Christian Kamm # Date 1237901656 -3600 # Node ID 45d73f0a9b43de845c88ca9e9ced28a2e20bf94a # Parent 8ebbad15fc999e27950536d9776a971c5f4bb425# Parent 9d308feaec27eefce40442e78f4ddb69e3419e77 Automated merge with http://hg.dsource.org/projects/ldc diff -r 8ebbad15fc99 -r 45d73f0a9b43 gen/toir.cpp --- a/gen/toir.cpp Tue Mar 24 03:14:22 2009 +0100 +++ b/gen/toir.cpp Tue Mar 24 14:34:16 2009 +0100 @@ -1104,14 +1104,32 @@ 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 @@ 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 { diff -r 8ebbad15fc99 -r 45d73f0a9b43 tests/mini/classes13_bug239.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/mini/classes13_bug239.d Tue Mar 24 14:34:16 2009 +0100 @@ -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); +}