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);