# HG changeset patch # User Frits van Bommel # Date 1236990125 -3600 # Node ID af625ea2d3cfff192095e44cb76fd15a5e0d517b # Parent 454f0c8acc4b41e0f088b48fc8a06c0598d5be85 Call _d_array_bounds when an associative array is indexed with a non-existent key (unless it's being assigned to). Closes #233. diff -r 454f0c8acc4b -r af625ea2d3cf gen/aa.cpp --- 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 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); }