diff --git a/gen/classes.cpp b/gen/classes.cpp index 9887ff1709..b368ee52bb 100644 --- a/gen/classes.cpp +++ b/gen/classes.cpp @@ -798,7 +798,7 @@ DValue* DtoNewClass(TypeClass* tc, NewExp* newexp) { DtoForceDeclareDsymbol(newexp->allocator); DFuncValue dfn(newexp->allocator, newexp->allocator->ir.irFunc->func); - DValue* res = DtoCallFunction(NULL, &dfn, newexp->newargs); + DValue* res = DtoCallFunction(newexp->loc, NULL, &dfn, newexp->newargs); mem = DtoBitCast(res->getRVal(), DtoType(tc), ".newclass_custom"); } // default allocator @@ -852,7 +852,7 @@ DValue* DtoNewClass(TypeClass* tc, NewExp* newexp) assert(newexp->arguments != NULL); DtoForceDeclareDsymbol(newexp->member); DFuncValue dfn(newexp->member, newexp->member->ir.irFunc->func, mem); - return DtoCallFunction(tc, &dfn, newexp->arguments); + return DtoCallFunction(newexp->loc, tc, &dfn, newexp->arguments); } // return default constructed class diff --git a/gen/llvmhelpers.h b/gen/llvmhelpers.h index 10a7ae8787..1c621e74b9 100644 --- a/gen/llvmhelpers.h +++ b/gen/llvmhelpers.h @@ -118,6 +118,6 @@ const LLFunctionType* DtoExtractFunctionType(const LLType* type); void DtoBuildDVarArgList(std::vector& args, llvm::PAListPtr& palist, TypeFunction* tf, Expressions* arguments, size_t argidx); /// -DValue* DtoCallFunction(Type* resulttype, DValue* fnval, Expressions* arguments); +DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions* arguments); #endif diff --git a/gen/tocall.cpp b/gen/tocall.cpp index 10f1e02ffe..cfbc7679a3 100644 --- a/gen/tocall.cpp +++ b/gen/tocall.cpp @@ -180,7 +180,7 @@ void DtoBuildDVarArgList(std::vector& args, llvm::PAListPtr& palist, T } -DValue* DtoCallFunction(Type* resulttype, DValue* fnval, Expressions* arguments) +DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions* arguments) { // the callee D type Type* calleeType = fnval->getType(); @@ -224,31 +224,40 @@ DValue* DtoCallFunction(Type* resulttype, DValue* fnval, Expressions* arguments) args.push_back(retvar); } - // then comes the 'this' argument - if (dfnval && dfnval->vthis) + // then comes a context argument... + if(usesthis || delegatecall || nestedcall) { - LLValue* thisarg = DtoBitCast(dfnval->vthis, argiter->get()); - ++argiter; - args.push_back(thisarg); - } - // or a delegate context arg - else if (delegatecall) - { - LLValue* ctxarg = DtoLoad(DtoGEPi(fnval->getRVal(), 0,0)); - assert(ctxarg->getType() == argiter->get()); - ++argiter; - args.push_back(ctxarg); - } - // or a nested function context arg - else if (nestedcall) - { - LLValue* contextptr = DtoNestedContext(dfnval->func->toParent2()->isFuncDeclaration()); - if (!contextptr) - contextptr = getNullPtr(getVoidPtrType()); + // ... which can be a 'this' argument + if (dfnval && dfnval->vthis) + { + LLValue* thisarg = DtoBitCast(dfnval->vthis, argiter->get()); + ++argiter; + args.push_back(thisarg); + } + // ... or a delegate context arg + else if (delegatecall) + { + LLValue* ctxarg = DtoLoad(DtoGEPi(fnval->getRVal(), 0,0)); + assert(ctxarg->getType() == argiter->get()); + ++argiter; + args.push_back(ctxarg); + } + // ... or a nested function context arg + else if (nestedcall) + { + LLValue* contextptr = DtoNestedContext(dfnval->func->toParent2()->isFuncDeclaration()); + if (!contextptr) + contextptr = getNullPtr(getVoidPtrType()); + else + contextptr = DtoBitCast(contextptr, getVoidPtrType()); + ++argiter; + args.push_back(contextptr); + } else - contextptr = DtoBitCast(contextptr, getVoidPtrType()); - ++argiter; - args.push_back(contextptr); + { + error(loc, "Context argument required but none given"); + fatal(); + } } // handle the rest of the arguments based on param passing style diff --git a/gen/toir.cpp b/gen/toir.cpp index 32464be0e8..b78a9b14db 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -886,7 +886,7 @@ DValue* CallExp::toElem(IRState* p) } } - return DtoCallFunction(type, fnval, arguments); + return DtoCallFunction(loc, type, fnval, arguments); } //////////////////////////////////////////////////////////////////////////////////////////