From 07888f95e49932c99cdbf8434643466bf9768bf1 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sat, 20 Oct 2012 17:08:51 +0200 Subject: [PATCH] D1: Fixed accessing parameters in contracts. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts the changes from commit f7e5245 and implements the proper fix – in D1, contracts are treated as normal nested functions. GitHub: Fix #138. --- gen/tocall.cpp | 19 +++++++++++-------- gen/toir.cpp | 7 ++++++- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/gen/tocall.cpp b/gen/tocall.cpp index ca2c22ea..d5c56007 100644 --- a/gen/tocall.cpp +++ b/gen/tocall.cpp @@ -410,18 +410,21 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions* // then comes a context argument... if(thiscall || delegatecall || nestedcall) { - if (dfnval && (dfnval->func->ident == Id::ensure || - dfnval->func->ident == Id::require)) - { +#if DMDV2 + if (dfnval && (dfnval->func->ident == Id::ensure || dfnval->func->ident == Id::require)) { // ... which can be the this "context" argument for a contract - // invocation (we do not generate a full nested context struct for - // these) + // invocation (in D2, we do not generate a full nested contexts + // for __require/__ensure as the needed parameters are passed + // explicitly, while in D1, the normal nested function handling + // mechanisms are used) LLValue* thisarg = DtoBitCast(DtoLoad(gIR->func()->thisArg), getVoidPtrType()); ++argiter; args.push_back(thisarg); } - else if (thiscall && dfnval && dfnval->vthis) - { + else +#endif + if (thiscall && dfnval && dfnval->vthis) + { // ... or a normal 'this' argument LLValue* thisarg = DtoBitCast(dfnval->vthis, *argiter); ++argiter; @@ -445,7 +448,7 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions* } else if (nestedcall) { - /// ... or a nested function context arg + // ... or a nested function context arg if (dfnval) { LLValue* contextptr = DtoNestedContext(loc, dfnval->func); contextptr = DtoBitCast(contextptr, getVoidPtrType()); diff --git a/gen/toir.cpp b/gen/toir.cpp index 3c9c2991..0da3fbfa 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -1562,11 +1562,16 @@ DValue* ThisExp::toElem(IRState* p) LLValue* v; Dsymbol* vdparent = vd->toParent2(); Identifier *ident = p->func()->decl->ident; +#if DMDV2 + // In D1, contracts are treated as normal nested methods, 'this' is + // just passed in the context struct along with any used parameters. if (ident == Id::ensure || ident == Id::require) { Logger::println("contract this exp"); v = p->func()->nestArg; v = DtoBitCast(v, DtoType(type)->getPointerTo()); - } else if (vdparent != p->func()->decl) { + } else +#endif + if (vdparent != p->func()->decl) { Logger::println("nested this exp"); #if STRUCTTHISREF return DtoNestedVariable(loc, type, vd, type->ty == Tstruct);