changeset 34:4648206ca213 trunk

[svn r38] * resizing dynamic arrays support * throw is replaced with assert(0) * catch is ignored * better foreach support * various bugfixes
author lindquist
date Tue, 09 Oct 2007 02:50:00 +0200
parents bc641b23a714
children 3cfcb944304e
files dmd/statement.c gen/arrays.c gen/arrays.h gen/elem.c gen/elem.h gen/statements.c gen/toir.c gen/tollvm.c gen/tollvm.h lphobos/build.sh lphobos/internal/mem.d test/arrays3.d test/bug7.d test/foreach2.d test/foreach3.d test/memory1.d test/throw1.d
diffstat 17 files changed, 296 insertions(+), 94 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/statement.c	Thu Oct 04 22:38:53 2007 +0200
+++ b/dmd/statement.c	Tue Oct 09 02:50:00 2007 +0200
@@ -1173,12 +1173,11 @@
 		if (arg->storageClass & (STCout | STCref | STClazy))
 		    error("no storage class for key %s", arg->ident->toChars());
 		TY keyty = arg->type->ty;
-		if ((keyty != Tint32 && keyty != Tuns32) ||
-		    (global.params.is64bit &&
-			    keyty != Tint64 && keyty != Tuns64)
+		if ((keyty != Tint32 && keyty != Tuns32) &&
+		    (global.params.is64bit && keyty != Tint64 && keyty != Tuns64)
 		   )
 		{
-		    error("foreach: key type must be int or uint, not %s", arg->type->toChars());
+		    error("foreach: key type must be %s, not %s", global.params.is64bit ? "int, uint, long or ulong" : "int or uint",arg->type->toChars());
 		}
 		Initializer *ie = new ExpInitializer(0, new IntegerExp(k));
 		VarDeclaration *var = new VarDeclaration(loc, arg->type, arg->ident, ie);
@@ -1315,13 +1314,12 @@
 	    }
 
 	    if (key &&
-		((key->type->ty != Tint32 && key->type->ty != Tuns32) ||
-		 (global.params.is64bit &&
-			key->type->ty != Tint64 && key->type->ty != Tuns64)
+		((key->type->ty != Tint32 && key->type->ty != Tuns32) &&
+		 (global.params.is64bit && key->type->ty != Tint64 && key->type->ty != Tuns64)
 	        )
 	       )
 	    {
-		error("foreach: key type must be int or uint, not %s", key->type->toChars());
+        error("foreach: key type must be %s, not %s", global.params.is64bit ? "int, uint, long or ulong" : "int or uint", key->type->toChars());
 	    }
 
 	    if (key && key->storage_class & (STCout | STCref))
--- a/gen/arrays.c	Thu Oct 04 22:38:53 2007 +0200
+++ b/gen/arrays.c	Tue Oct 09 02:50:00 2007 +0200
@@ -98,7 +98,7 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-llvm::Value* LLVM_DtoArrayAssign(llvm::Value* dst, llvm::Value* src)
+void LLVM_DtoArrayAssign(llvm::Value* dst, llvm::Value* src)
 {
     assert(gIR);
     if (dst->getType() == src->getType())
@@ -118,7 +118,7 @@
         llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false);
         llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
 
-        return new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
+        new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
     }
     else
     {
@@ -130,14 +130,11 @@
         const llvm::ArrayType* arrty = llvm::cast<llvm::ArrayType>(src->getType()->getContainedType(0));
         llvm::Type* dstty = llvm::PointerType::get(arrty->getElementType());
 
-        llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
-        llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
-
-        llvm::Value* dstlen = LLVM_DtoGEP(dst,zero,zero,"tmp",gIR->scopebb());
+        llvm::Value* dstlen = LLVM_DtoGEPi(dst,0,0,"tmp",gIR->scopebb());
         llvm::Value* srclen = llvm::ConstantInt::get(LLVM_DtoSize_t(), arrty->getNumElements(), false);
         new llvm::StoreInst(srclen, dstlen, gIR->scopebb());
 
-        llvm::Value* dstptr = LLVM_DtoGEP(dst,zero,one,"tmp",gIR->scopebb());
+        llvm::Value* dstptr = LLVM_DtoGEPi(dst,0,1,"tmp",gIR->scopebb());
         llvm::Value* srcptr = new llvm::BitCastInst(src,dstty,"tmp",gIR->scopebb());
         new llvm::StoreInst(srcptr, dstptr, gIR->scopebb());
     }
@@ -350,6 +347,7 @@
     return ret;
 }
 
+//////////////////////////////////////////////////////////////////////////////////////////
 void LLVM_DtoArrayCopy(elem* dst, elem* src)
 {
     Logger::cout() << "Array copy ((((" << *src->mem << ")))) into ((((" << *dst->mem << "))))\n";
@@ -387,3 +385,34 @@
     values.push_back(ptr);
     return llvm::ConstantStruct::get(type,values);
 }
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLVM_DtoNewDynArray(llvm::Value* dst, llvm::Value* dim, const llvm::Type* ty)
+{
+    size_t sz = gTargetData->getTypeSize(ty);
+    llvm::ConstantInt* n = llvm::ConstantInt::get(LLVM_DtoSize_t(), sz, false);
+    llvm::Value* bytesize = llvm::BinaryOperator::createMul(n,dim,"tmp",gIR->scopebb());
+
+    llvm::Value* nullptr = llvm::ConstantPointerNull::get(llvm::PointerType::get(ty));
+
+    llvm::Value* newptr = LLVM_DtoRealloc(nullptr, bytesize);
+
+    llvm::Value* lenptr = LLVM_DtoGEPi(dst,0,0,"tmp",gIR->scopebb());
+    new llvm::StoreInst(dim,lenptr,gIR->scopebb());
+    llvm::Value* ptrptr = LLVM_DtoGEPi(dst,0,1,"tmp",gIR->scopebb());
+    new llvm::StoreInst(newptr,ptrptr,gIR->scopebb());
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLVM_DtoResizeDynArray(llvm::Value* arr, llvm::Value* sz)
+{
+    llvm::Value* ptr = LLVM_DtoGEPi(arr, 0, 1, "tmp", gIR->scopebb());
+    llvm::Value* ptrld = new llvm::LoadInst(ptr,"tmp",gIR->scopebb());
+    llvm::Value* newptr = LLVM_DtoRealloc(ptrld, sz);
+    new llvm::StoreInst(newptr,ptr,gIR->scopebb());
+    llvm::Value* len = LLVM_DtoGEPi(arr, 0, 0, "tmp", gIR->scopebb());
+    new llvm::StoreInst(sz,len,gIR->scopebb());
+}
+
+
+
--- a/gen/arrays.h	Thu Oct 04 22:38:53 2007 +0200
+++ b/gen/arrays.h	Tue Oct 09 02:50:00 2007 +0200
@@ -2,21 +2,18 @@
 #define LLVMC_GEN_ARRAYS_H
 
 const llvm::StructType* LLVM_DtoArrayType(Type* t);
-
 const llvm::ArrayType* LLVM_DtoStaticArrayType(Type* t);
 
+llvm::Constant* LLVM_DtoArrayInitializer(ArrayInitializer* si);
+llvm::Constant* LLVM_DtoConstantSlice(llvm::Constant* dim, llvm::Constant* ptr);
+
+void LLVM_DtoArrayCopy(elem* dst, elem* src);
+void LLVM_DtoArrayInit(llvm::Value* l, llvm::Value* r);
+void LLVM_DtoArrayAssign(llvm::Value* l, llvm::Value* r);
+void LLVM_DtoSetArray(llvm::Value* arr, llvm::Value* dim, llvm::Value* ptr);
 llvm::Value* LLVM_DtoNullArray(llvm::Value* v);
 
-llvm::Value* LLVM_DtoArrayAssign(llvm::Value* l, llvm::Value* r);
-
-void LLVM_DtoSetArray(llvm::Value* arr, llvm::Value* dim, llvm::Value* ptr);
-
-llvm::Constant* LLVM_DtoArrayInitializer(ArrayInitializer* si);
-
-void LLVM_DtoArrayCopy(elem* dst, elem* src);
-
-void LLVM_DtoArrayInit(llvm::Value* l, llvm::Value* r);
-
-llvm::Constant* LLVM_DtoConstantSlice(llvm::Constant* dim, llvm::Constant* ptr);
+void LLVM_DtoNewDynArray(llvm::Value* dst, llvm::Value* dim, const llvm::Type* ty);
+void LLVM_DtoResizeDynArray(llvm::Value* arr, llvm::Value* sz);
 
 #endif // LLVMC_GEN_ARRAYS_H
--- a/gen/elem.c	Thu Oct 04 22:38:53 2007 +0200
+++ b/gen/elem.c	Tue Oct 09 02:50:00 2007 +0200
@@ -34,7 +34,8 @@
         break;
 
     case VAR:
-    case REF: {
+    case REF:
+    case ARRAYLEN:
         if (val) {
             return val;
         }
@@ -52,7 +53,6 @@
                 return new llvm::LoadInst(mem, "tmp", gIR->scopebb());
             }
         }
-    }
 
     case VAL:
     case NUL:
--- a/gen/elem.h	Thu Oct 04 22:38:53 2007 +0200
+++ b/gen/elem.h	Tue Oct 09 02:50:00 2007 +0200
@@ -19,7 +19,8 @@
         CONST,
         NUL,
         REF,
-        SLICE
+        SLICE,
+        ARRAYLEN
     };
 
 public:
--- a/gen/statements.c	Thu Oct 04 22:38:53 2007 +0200
+++ b/gen/statements.c	Tue Oct 09 02:50:00 2007 +0200
@@ -35,40 +35,17 @@
     Logger::println("CompoundStatement::toIR(%d):\n<<<\n%s>>>", csi++, toChars());
     LOG_SCOPE;
 
-    /*
-    const char* labelname;
-    bool insterm = false;
-
-    if (!p->scopes()) {
-        labelname = "bb";
-        insterm = true;
-    }
-    else
-        labelname = "entry";
-
-    //if (!llvm::isa<llvm::TerminatorInst>(p->topfunc()->back().back()))
-    //    insterm = true;
-
-    llvm::BasicBlock* bb = new llvm::BasicBlock(labelname, p->topfunc());
-
-    if (insterm) {
-        new llvm::BranchInst(bb,p->topbb());
-    }
-
-    p->bbs.push(bb);
-    */
-
-    size_t n = statements->dim;
-    for (size_t i=0; i<n; i++)
+    for (int i=0; i<statements->dim; i++)
     {
         Statement* s = (Statement*)statements->data[i];
         if (s)
-        s->toIR(p);
-        else
-        Logger::println("NULL statement found in CompoundStatement !! :S");
+            s->toIR(p);
+        else {
+            Logger::println("NULL statement found in CompoundStatement !! :S");
+            assert(0);
+        }
     }
 
-    //p->bbs.pop();
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -476,17 +453,17 @@
     Logger::println("TryCatchStatement::toIR(%d): %s", wsi++, toChars());
     LOG_SCOPE;
 
-    assert(0 && "try-catch is not properly");
+    Logger::println("*** ATTENTION: try-catch is not yet fully implemented, only the try block will be emitted.");
 
     assert(body);
     body->toIR(p);
 
-    assert(catches);
+    /*assert(catches);
     for(size_t i=0; i<catches->dim; ++i)
     {
         Catch* c = (Catch*)catches->data[i];
         c->handler->toIR(p);
-    }
+    }*/
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -497,11 +474,16 @@
     Logger::println("ThrowStatement::toIR(%d): %s", wsi++, toChars());
     LOG_SCOPE;
 
-    assert(0 && "throw is not implemented");
+    Logger::println("*** ATTENTION: throw is not yet implemented, replacing expression with assert(0);");
 
+    llvm::Value* line = llvm::ConstantInt::get(llvm::Type::Int32Ty, loc.linnum, false);
+    LLVM_DtoAssert(NULL, line, NULL);
+
+    /*
     assert(exp);
     elem* e = exp->toElem(p);
     delete e;
+    */
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -622,7 +604,6 @@
     LOG_SCOPE;
 
     //assert(arguments->dim == 1);
-    assert(key == 0);
     assert(value != 0);
     assert(body != 0);
     assert(aggr != 0);
@@ -642,6 +623,7 @@
 
     const llvm::Type* keytype = key ? LLVM_DtoType(key->type) : LLVM_DtoSize_t();
     llvm::Value* keyvar = new llvm::AllocaInst(keytype, "foreachkey", p->topallocapoint());
+    if (key) key->llvmValue = keyvar;
 
     const llvm::Type* valtype = LLVM_DtoType(value->type);
     llvm::Value* valvar = new llvm::AllocaInst(keytype, "foreachval", p->topallocapoint());
--- a/gen/toir.c	Thu Oct 04 22:38:53 2007 +0200
+++ b/gen/toir.c	Tue Oct 09 02:50:00 2007 +0200
@@ -118,8 +118,10 @@
                     e->mem = tid->llvmValue;
                     e->type = elem::VAR;
                 }
-                else
-                assert(0 && "only magic supported is typeinfo");
+                else {
+                    Logger::println("unsupported: %s\n", vd->toChars());
+                    assert(0 && "only magic supported is typeinfo");
+                }
             }
             return e;
         }
@@ -331,9 +333,23 @@
         elem* r = e2->toElem(p);
     p->lvals.pop_back();
 
+    if (l->type == elem::ARRAYLEN)
+    {
+        LLVM_DtoResizeDynArray(l->mem, r->getValue());
+        delete r;
+        delete l;
+        return 0;
+    }
+
     // handle function argument - allocate temp storage for it :/ annoying
     if (l->mem == 0) {
-        LLVM_DtoGiveArgumentStorage(l);
+        assert(l->val);
+        if (llvm::isa<llvm::Argument>(l->val))
+            LLVM_DtoGiveArgumentStorage(l);
+        else {
+            Logger::cout() << "here it comes... " << *l->val << '\n';
+            assert(0);
+        }
     }
     //e->val = l->store(r->getValue());
 
@@ -1826,12 +1842,16 @@
             if (arguments->dim == 1) {
                 elem* sz = ((Expression*)arguments->data[0])->toElem(p);
                 llvm::Value* dimval = sz->getValue();
-                llvm::Value* usedimval = dimval;
+                /*llvm::Value* usedimval = dimval;
                 if (dimval->getType() != llvm::Type::Int32Ty)
-                    usedimval = new llvm::TruncInst(dimval, llvm::Type::Int32Ty,"tmp",p->scopebb());
-                e->mem = new llvm::MallocInst(t,usedimval,"tmp",p->scopebb());
+                    usedimval = new llvm::TruncInst(dimval, llvm::Type::Int32Ty,"tmp",p->scopebb());*/
 
-                LLVM_DtoSetArray(p->toplval(), dimval, e->mem);
+                //e->mem = LLVM_DtoRealloc(0,t);
+                //new llvm::MallocInst(t,usedimval,"tmp",p->scopebb());
+
+                //LLVM_DtoSetArray(p->toplval(), dimval, e->mem);
+
+                LLVM_DtoNewDynArray(p->toplval(), dimval, t);
                 delete sz;
             }
             else {
@@ -1948,11 +1968,18 @@
     elem* e = new elem;
     elem* u = e1->toElem(p);
 
-    llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
-    llvm::Value* ptr = LLVM_DtoGEP(u->mem,zero,zero,"tmp",p->scopebb());
-    e->val = new llvm::LoadInst(ptr, "tmp", p->scopebb());
-    e->type = elem::VAL;
-
+    if (p->inLvalue)
+    {
+        e->mem = u->mem;
+        e->type = elem::ARRAYLEN;
+    }
+    else
+    {
+        llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
+        llvm::Value* ptr = LLVM_DtoGEP(u->mem,zero,zero,"tmp",p->scopebb());
+        e->val = new llvm::LoadInst(ptr, "tmp", p->scopebb());
+        e->type = elem::VAL;
+    }
     delete u;
 
     return e;
@@ -1965,27 +1992,16 @@
     Logger::print("AssertExp::toElem: %s | %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
-    elem* e = new elem;
     elem* u = e1->toElem(p);
-    elem* m = msg ? msg->toElem(p) : 0;
+    elem* m = msg ? msg->toElem(p) : NULL;
 
-    std::vector<llvm::Value*> llargs;
-    llargs.resize(3);
-    llargs[0] = LLVM_DtoBoolean(u->getValue());
-    llargs[1] = llvm::ConstantInt::get(llvm::Type::Int32Ty, loc.linnum, false);
-    llargs[2] = m ? m->val : llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty));
-    
+    llvm::Value* loca = llvm::ConstantInt::get(llvm::Type::Int32Ty, loc.linnum, false);
+    LLVM_DtoAssert(u->getValue(), loca, m ? m->val : NULL);
+
     delete m;
     delete u;
-    
-    //Logger::cout() << *llargs[0] << '|' << *llargs[1] << '\n';
-    
-    llvm::Function* fn = LLVM_D_GetRuntimeFunction(p->module, "_d_assert");
-    assert(fn);
-    llvm::CallInst* call = new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", p->scopebb());
-    call->setCallingConv(llvm::CallingConv::C);
 
-    return e;
+    return new elem;
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
--- a/gen/tollvm.c	Thu Oct 04 22:38:53 2007 +0200
+++ b/gen/tollvm.c	Tue Oct 09 02:50:00 2007 +0200
@@ -997,3 +997,66 @@
     l->mem = allocainst;
     l->vardecl->llvmValue = l->mem;
 }
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Value* LLVM_DtoRealloc(llvm::Value* ptr, const llvm::Type* ty)
+{
+    /*size_t sz = gTargetData->getTypeSize(ty);
+    llvm::ConstantInt* n = llvm::ConstantInt::get(LLVM_DtoSize_t(), sz, false);
+    if (ptr == 0) {
+        llvm::PointerType* i8pty = llvm::PointerType::get(llvm::Type::Int8Ty);
+        ptr = llvm::ConstantPointerNull::get(i8pty);
+    }
+    return LLVM_DtoRealloc(ptr, n);*/
+    return NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Value* LLVM_DtoRealloc(llvm::Value* ptr, llvm::Value* n)
+{
+    assert(ptr);
+    assert(n);
+
+    llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_realloc");
+    assert(fn);
+
+    llvm::Value* newptr = ptr;
+
+    llvm::PointerType* i8pty = llvm::PointerType::get(llvm::Type::Int8Ty);
+    if (ptr->getType() != i8pty) {
+        newptr = new llvm::BitCastInst(ptr,i8pty,"tmp",gIR->scopebb());
+    }
+
+    std::vector<llvm::Value*> args;
+    args.push_back(newptr);
+    args.push_back(n);
+    llvm::Value* ret = new llvm::CallInst(fn, args.begin(), args.end(), "tmprealloc", gIR->scopebb());
+
+    return ret->getType() == ptr->getType() ? ret : new llvm::BitCastInst(ret,ptr->getType(),"tmp",gIR->scopebb());
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void LLVM_DtoAssert(llvm::Value* cond, llvm::Value* loc, llvm::Value* msg)
+{
+    assert(loc);
+    std::vector<llvm::Value*> llargs;
+    llargs.resize(3);
+    llargs[0] = cond ? LLVM_DtoBoolean(cond) : llvm::ConstantInt::getFalse();
+    llargs[1] = loc;
+    llargs[2] = msg ? msg : llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty));
+
+    llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_assert");
+    assert(fn);
+    llvm::CallInst* call = new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
+    call->setCallingConv(llvm::CallingConv::C);
+}
+
+
+
+
+
+
+
--- a/gen/tollvm.h	Thu Oct 04 22:38:53 2007 +0200
+++ b/gen/tollvm.h	Tue Oct 09 02:50:00 2007 +0200
@@ -44,4 +44,9 @@
 
 void LLVM_DtoGiveArgumentStorage(elem* e);
 
+llvm::Value* LLVM_DtoRealloc(llvm::Value* ptr, const llvm::Type* ty);
+llvm::Value* LLVM_DtoRealloc(llvm::Value* ptr, llvm::Value* len);
+
+void LLVM_DtoAssert(llvm::Value* cond, llvm::Value* loc, llvm::Value* msg);
+
 #include "enums.h"
--- a/lphobos/build.sh	Thu Oct 04 22:38:53 2007 +0200
+++ b/lphobos/build.sh	Tue Oct 09 02:50:00 2007 +0200
@@ -9,14 +9,15 @@
 # build runtime
 $dc_cmd internal/contract.d \
         internal/arrays.d \
+        internal/mem.d \
         internal/moduleinit.d \
         -c -noruntime -odobj || exit 1
 
 llvm-as -f -o=obj/moduleinit_backend.bc internal/moduleinit_backend.ll || exit 1
-llvm-link -f -o=../lib/llvmdcore.bc obj/contract.bc obj/arrays.bc obj/moduleinit.bc obj/moduleinit_backend.bc || exit 1
+llvm-link -f -o=../lib/llvmdcore.bc obj/contract.bc obj/arrays.bc obj/mem.bc obj/moduleinit.bc obj/moduleinit_backend.bc || exit 1
 
 $dc_cmd internal/objectimpl.d -c -odobj || exit 1
-llvm-link -f -o=obj/all.bc obj/contract.bc obj/arrays.bc obj/moduleinit.bc obj/objectimpl.bc obj/moduleinit_backend.bc || exit 1
+llvm-link -f -o=obj/all.bc obj/contract.bc obj/arrays.bc obj/mem.bc obj/moduleinit.bc obj/objectimpl.bc obj/moduleinit_backend.bc || exit 1
 
 opt -f -std-compile-opts -o=../lib/llvmdcore.bc obj/all.bc || exit 1
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lphobos/internal/mem.d	Tue Oct 09 02:50:00 2007 +0200
@@ -0,0 +1,16 @@
+module internal.mem;
+
+extern(C):
+
+void* realloc(void*,size_t);
+void free(void*);
+
+void* _d_realloc(void* ptr, size_t n)
+{
+    return realloc(ptr, n);
+}
+
+void _d_free(void* ptr)
+{
+    free(ptr);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/arrays3.d	Tue Oct 09 02:50:00 2007 +0200
@@ -0,0 +1,10 @@
+module arrays3;
+
+void main()
+{
+    int[] arr;
+    {arr = new int[25];}
+    {assert(arr.length == 25);}
+    {arr.length = arr.length + 5;}
+    {assert(arr.length == 30);}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug7.d	Tue Oct 09 02:50:00 2007 +0200
@@ -0,0 +1,14 @@
+module bug7;
+
+class love { }
+void bug() {
+    love[] child;
+    child.length=1;
+    assert(child[0] is null);
+    child[0]=null;
+    assert(child[0] is null);
+}
+void main()
+{
+    bug();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/foreach2.d	Tue Oct 09 02:50:00 2007 +0200
@@ -0,0 +1,15 @@
+module foreach2;
+
+void main()
+{
+    static arr = [1.0, 2.0, 4.0, 8.0, 16.0];
+    foreach(i,v; arr)
+    {
+        printf("arr[%d] = %f\n", i, v);
+    }
+    printf("-------------------------------\n");
+    foreach_reverse(i,v; arr)
+    {
+        printf("arr[%d] = %f\n", i, v);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/foreach3.d	Tue Oct 09 02:50:00 2007 +0200
@@ -0,0 +1,19 @@
+module foreach3;
+
+void main()
+{
+    static str = ['h','e','l','l','o'];
+    foreach(i,v; str) {
+        printf("%c",v);
+    }
+    printf("\n");
+
+    foreach(i,v; str) {
+        v++;
+    }
+
+    foreach(i,v; str) {
+        printf("%c",v);
+    }
+    printf("\n");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/memory1.d	Tue Oct 09 02:50:00 2007 +0200
@@ -0,0 +1,10 @@
+module memory1;
+
+void main()
+{
+    auto a = new int[16];
+    {printf("array.length = %u\n", a.length);}
+    {a.length = a.length + 1;}
+    {printf("array.length = %u\n", a.length);}
+    {assert(a.length == 17);}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/throw1.d	Tue Oct 09 02:50:00 2007 +0200
@@ -0,0 +1,26 @@
+module throw1;
+
+extern(C) int rand();
+
+class C
+{
+}
+
+void func()
+{
+    if (rand() & 1)
+        throw new C;
+}
+
+int main()
+{
+    try
+    {
+        func();
+    }
+    catch(Object)
+    {
+        return 1;
+    }
+    return 0;
+}