# HG changeset patch # User Frits van Bommel # Date 1240175703 -7200 # Node ID 00f377e03423500595eeac40422ab1879efd7625 # Parent 837f4856086312fc94c1260a094d93d68056a0d5 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). diff -r 837f48560863 -r 00f377e03423 gen/functions.cpp --- 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(*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);