Call _d_array_bounds when an associative array is indexed with a non-existent

key (unless it's being assigned to). Closes #233.
This commit is contained in:
Frits van Bommel
2009-03-14 01:22:05 +01:00
parent 1e6bd8f8e8
commit 85a3433791

View File

@@ -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 @@ DValue* DtoAAIndex(Loc& loc, Type* type, DValue* aa, DValue* key, bool lvalue)
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);
}