From d0a8ee95738a2177b12684a055b2e07376f393da Mon Sep 17 00:00:00 2001 From: Frits van Bommel Date: Fri, 20 Mar 2009 15:50:01 +0100 Subject: [PATCH] Return null from a static class to interface cast if the class reference was null. Fixes #237. --- gen/classes.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/gen/classes.cpp b/gen/classes.cpp index 2c863937..af666c00 100644 --- a/gen/classes.cpp +++ b/gen/classes.cpp @@ -1067,13 +1067,21 @@ DValue* DtoCastClass(DValue* val, Type* _to) IrInterface* iri = iriter->second; // offset pointer LLValue* v = val->getRVal(); + LLValue* orig = v; v = DtoGEPi(v, 0, iri->index); + const LLType* ifType = DtoType(_to); if (Logger::enabled()) { Logger::cout() << "V = " << *v << std::endl; - Logger::cout() << "T = " << *DtoType(_to) << std::endl; + Logger::cout() << "T = " << *ifType << std::endl; } - v = DtoBitCast(v, DtoType(_to)); + v = DtoBitCast(v, ifType); + // Check whether the original value was null, and return null if so. + // Sure we could have jumped over the code above in this case, but + // it's just a GEP and (maybe) a pointer-to-pointer BitCast, so it + // should be pretty cheap and perfectly safe even if the original was null. + LLValue* isNull = gIR->ir->CreateICmpEQ(orig, LLConstant::getNullValue(orig->getType()), ".nullcheck"); + v = gIR->ir->CreateSelect(isNull, LLConstant::getNullValue(ifType), v, ".interface"); // return r-value return new DImValue(_to, v); }