Mercurial > projects > ldc
changeset 1226:00f377e03423
Fix a problem which occurred when a function type was forward-referenced by
parameter types.
This was intended to fix the following test case:
{{{
void delegate(Hit) dg;
struct Hit { void delegate(Hit) a; }
}}}
which ChristianK reduced from a problem downs had on IRC.
It also seems to fix mini/compile_delegate.d (which turns out to be quite
similar, but produced a different error message).
author | Frits van Bommel <fvbommel wxs.nl> |
---|---|
date | Sun, 19 Apr 2009 23:15:03 +0200 |
parents | 837f48560863 |
children | a16b587aab58 |
files | gen/functions.cpp |
diffstat | 1 files changed, 41 insertions(+), 12 deletions(-) [+] |
line wrap: on
line diff
--- a/gen/functions.cpp Sun Apr 19 19:28:10 2009 +0200 +++ b/gen/functions.cpp Sun Apr 19 23:15:03 2009 +0200 @@ -45,8 +45,9 @@ gABI->newFunctionType(f); } - // start new ir funcTy - f->fty.reset(); + // Do not modify f->fty yet; this function may be called recursively if any + // of the argument types refer to this type. + IrFuncTy fty; // llvm idx counter size_t lidx = 0; @@ -54,7 +55,7 @@ // main needs a little special handling if (ismain) { - f->fty.ret = new IrFuncTyArg(Type::tint32, false); + fty.ret = new IrFuncTyArg(Type::tint32, false); } // sane return value else @@ -65,7 +66,7 @@ if (f->linkage != LINKintrinsic) if (gABI->returnInArg(f)) { - f->fty.arg_sret = new IrFuncTyArg(rt, true, StructRet | NoAlias | NoCapture); + fty.arg_sret = new IrFuncTyArg(rt, true, StructRet | NoAlias | NoCapture); rt = Type::tvoid; lidx++; } @@ -74,7 +75,7 @@ { a = se; } - f->fty.ret = new IrFuncTyArg(rt, false, a); + fty.ret = new IrFuncTyArg(rt, false, a); } lidx++; @@ -82,14 +83,14 @@ if (thistype) { bool toref = (thistype->toBasetype()->ty == Tstruct); - f->fty.arg_this = new IrFuncTyArg(thistype, toref); + fty.arg_this = new IrFuncTyArg(thistype, toref); lidx++; } // and nested functions else if (nesttype) { - f->fty.arg_nest = new IrFuncTyArg(nesttype, false); + fty.arg_nest = new IrFuncTyArg(nesttype, false); lidx++; } @@ -103,16 +104,16 @@ if (f->varargs == 1) { // _arguments - f->fty.arg_arguments = new IrFuncTyArg(Type::typeinfo->type->arrayOf(), false); + fty.arg_arguments = new IrFuncTyArg(Type::typeinfo->type->arrayOf(), false); lidx++; // _argptr - f->fty.arg_argptr = new IrFuncTyArg(Type::tvoid->pointerTo(), false, NoAlias | NoCapture); + fty.arg_argptr = new IrFuncTyArg(Type::tvoid->pointerTo(), false, NoAlias | NoCapture); lidx++; } } else if (f->linkage == LINKc) { - f->fty.c_vararg = true; + fty.c_vararg = true; } else { @@ -127,7 +128,7 @@ if (ismain && nargs == 0) { Type* mainargs = Type::tchar->arrayOf()->arrayOf(); - f->fty.args.push_back(new IrFuncTyArg(mainargs, false)); + fty.args.push_back(new IrFuncTyArg(mainargs, false)); lidx++; } // add explicit parameters @@ -163,10 +164,38 @@ a |= DtoShouldExtend(argtype); } - f->fty.args.push_back(new IrFuncTyArg(argtype, byref, a)); + fty.args.push_back(new IrFuncTyArg(argtype, byref, a)); lidx++; } + // If the function type was forward referenced by one of the parameter types, + // it has now been set. + if (f->ir.type) { + for (size_t i = 0; i < fty.args.size(); i++) { + Logger::cout() << "Arg type: " << *fty.args[i]->ltype << '\n'; + } + + // Notify ABI that we won't be needing it for this function type anymore. + gABI->doneWithFunctionType(); + + // Some cleanup of memory we won't use + delete fty.ret; + delete fty.arg_sret; + delete fty.arg_this; + delete fty.arg_nest; + delete fty.arg_arguments; + delete fty.arg_argptr; + for (IrFuncTy::ArgIter It = fty.args.begin(), E = fty.args.end(); It != E; ++It) { + delete *It; + } + + Logger::cout() << "Function type: " << **f->ir.type << '\n'; + return llvm::cast<LLFunctionType>(*f->ir.type); + } + + // Now we can modify f->fty safely. + f->fty = fty; + if (f->linkage != LINKintrinsic) { // let the abi rewrite the types as necesary gABI->rewriteFunctionType(f);