changeset 1115:af625ea2d3cf

Call _d_array_bounds when an associative array is indexed with a non-existent key (unless it's being assigned to). Closes #233.
author Frits van Bommel <fvbommel wxs.nl>
date Sat, 14 Mar 2009 01:22:05 +0100
parents 454f0c8acc4b
children d584cda84b00
files gen/aa.cpp
diffstat 1 files changed, 36 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/gen/aa.cpp	Fri Mar 13 19:22:40 2009 +0100
+++ b/gen/aa.cpp	Sat Mar 14 01:22:05 2009 +0100
@@ -1,6 +1,7 @@
 #include "gen/llvm.h"
 
 #include "mtype.h"
+#include "module.h"
 #include "declaration.h"
 #include "aggregate.h"
 
@@ -11,6 +12,7 @@
 #include "gen/logger.h"
 #include "gen/irstate.h"
 #include "gen/dvalue.h"
+#include "ir/irmodule.h"
 
 // makes sure the key value lives in memory so it can be passed to the runtime functions without problems
 // returns the pointer
@@ -91,6 +93,40 @@
     if (ret->getType() != targettype)
         ret = DtoBitCast(ret, targettype);
 
+    // Only check bounds for rvalues ('aa[key]').
+    // Lvalue use ('aa[key] = value') auto-adds an element.
+    if (!lvalue) {
+        llvm::BasicBlock* oldend = gIR->scopeend();
+        llvm::BasicBlock* failbb = llvm::BasicBlock::Create("aaboundscheckfail", gIR->topfunc(), oldend);
+        llvm::BasicBlock* okbb = llvm::BasicBlock::Create("aaboundsok", gIR->topfunc(), oldend);
+
+        LLValue* nullaa = LLConstant::getNullValue(ret->getType());
+        LLValue* cond = gIR->ir->CreateICmpNE(nullaa, ret, "aaboundscheck");
+        gIR->ir->CreateCondBr(cond, okbb, failbb);
+
+        // set up failbb to call the array bounds error runtime function
+
+        gIR->scope() = IRScope(failbb, okbb);
+
+        std::vector<LLValue*> args;
+
+        // file param
+        args.push_back(DtoLoad(gIR->dmodule->ir.irModule->fileName));
+
+        // line param
+        LLConstant* c = DtoConstUint(loc.linnum);
+        args.push_back(c);
+
+        // call
+        llvm::Function* errorfn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_array_bounds");
+        gIR->CreateCallOrInvoke(errorfn, args.begin(), args.end());
+
+        // the function does not return
+        gIR->ir->CreateUnreachable();
+
+        // if ok, proceed in okbb
+        gIR->scope() = IRScope(okbb, oldend);
+    }
     return new DVarValue(type, ret);
 }