changeset 1128:83ef1e7cde70

Return null from a static class to interface cast if the class reference was null. Fixes #237.
author Frits van Bommel <fvbommel wxs.nl>
date Fri, 20 Mar 2009 15:50:01 +0100
parents 3e98925bcc39
children 8403fec8c34c
files gen/classes.cpp
diffstat 1 files changed, 10 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/gen/classes.cpp	Fri Mar 20 15:47:42 2009 +0100
+++ b/gen/classes.cpp	Fri Mar 20 15:50:01 2009 +0100
@@ -1067,13 +1067,21 @@
             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);
         }