From 3db5b9bb98c527ff23a878e839ec9d3586b82d72 Mon Sep 17 00:00:00 2001 From: Tomas Lindquist Olsen Date: Tue, 9 Oct 2007 02:50:00 +0200 Subject: [PATCH] [svn r38] * resizing dynamic arrays support * throw is replaced with assert(0) * catch is ignored * better foreach support * various bugfixes --- dmd/statement.c | 14 ++++---- gen/arrays.c | 43 +++++++++++++++++++++---- gen/arrays.h | 21 ++++++------ gen/elem.c | 4 +-- gen/elem.h | 3 +- gen/statements.c | 50 ++++++++++------------------- gen/toir.c | 72 ++++++++++++++++++++++++++---------------- gen/tollvm.c | 63 ++++++++++++++++++++++++++++++++++++ gen/tollvm.h | 5 +++ lphobos/build.sh | 5 +-- lphobos/internal/mem.d | 16 ++++++++++ test/arrays3.d | 10 ++++++ test/bug7.d | 14 ++++++++ test/foreach2.d | 15 +++++++++ test/foreach3.d | 19 +++++++++++ test/memory1.d | 10 ++++++ test/throw1.d | 26 +++++++++++++++ 17 files changed, 296 insertions(+), 94 deletions(-) create mode 100644 lphobos/internal/mem.d create mode 100644 test/arrays3.d create mode 100644 test/bug7.d create mode 100644 test/foreach2.d create mode 100644 test/foreach3.d create mode 100644 test/memory1.d create mode 100644 test/throw1.d diff --git a/dmd/statement.c b/dmd/statement.c index b229a65a..a21eabae 100644 --- a/dmd/statement.c +++ b/dmd/statement.c @@ -1173,12 +1173,11 @@ Statement *ForeachStatement::semantic(Scope *sc) 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 @@ Statement *ForeachStatement::semantic(Scope *sc) } 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)) diff --git a/gen/arrays.c b/gen/arrays.c index 042a6f80..dde37ad6 100644 --- a/gen/arrays.c +++ b/gen/arrays.c @@ -98,7 +98,7 @@ llvm::Value* LLVM_DtoNullArray(llvm::Value* v) ////////////////////////////////////////////////////////////////////////////////////////// -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 @@ llvm::Value* LLVM_DtoArrayAssign(llvm::Value* dst, llvm::Value* src) 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 @@ llvm::Value* LLVM_DtoArrayAssign(llvm::Value* dst, llvm::Value* src) const llvm::ArrayType* arrty = llvm::cast(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 @@ static llvm::Value* get_slice_ptr(elem* e, llvm::Value*& sz) return ret; } +////////////////////////////////////////////////////////////////////////////////////////// void LLVM_DtoArrayCopy(elem* dst, elem* src) { Logger::cout() << "Array copy ((((" << *src->mem << ")))) into ((((" << *dst->mem << "))))\n"; @@ -387,3 +385,34 @@ llvm::Constant* LLVM_DtoConstantSlice(llvm::Constant* dim, llvm::Constant* ptr) 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()); +} + + + diff --git a/gen/arrays.h b/gen/arrays.h index 57c0f772..f0b2d772 100644 --- a/gen/arrays.h +++ b/gen/arrays.h @@ -2,21 +2,18 @@ #define LLVMC_GEN_ARRAYS_H const llvm::StructType* LLVM_DtoArrayType(Type* t); - const llvm::ArrayType* LLVM_DtoStaticArrayType(Type* t); -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_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); + +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 diff --git a/gen/elem.c b/gen/elem.c index cde3966f..4a17f75f 100644 --- a/gen/elem.c +++ b/gen/elem.c @@ -34,7 +34,8 @@ llvm::Value* elem::getValue() break; case VAR: - case REF: { + case REF: + case ARRAYLEN: if (val) { return val; } @@ -52,7 +53,6 @@ llvm::Value* elem::getValue() return new llvm::LoadInst(mem, "tmp", gIR->scopebb()); } } - } case VAL: case NUL: diff --git a/gen/elem.h b/gen/elem.h index 86ba8674..6bee5532 100644 --- a/gen/elem.h +++ b/gen/elem.h @@ -19,7 +19,8 @@ struct elem : Object CONST, NUL, REF, - SLICE + SLICE, + ARRAYLEN }; public: diff --git a/gen/statements.c b/gen/statements.c index f654da1c..f44bfb40 100644 --- a/gen/statements.c +++ b/gen/statements.c @@ -35,40 +35,17 @@ void CompoundStatement::toIR(IRState* p) 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(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; idim; 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 @@ void TryCatchStatement::toIR(IRState* p) 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; idim; ++i) { Catch* c = (Catch*)catches->data[i]; c->handler->toIR(p); - } + }*/ } ////////////////////////////////////////////////////////////////////////////// @@ -497,11 +474,16 @@ void ThrowStatement::toIR(IRState* p) 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 @@ void ForeachStatement::toIR(IRState* p) LOG_SCOPE; //assert(arguments->dim == 1); - assert(key == 0); assert(value != 0); assert(body != 0); assert(aggr != 0); @@ -642,6 +623,7 @@ void ForeachStatement::toIR(IRState* p) 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()); diff --git a/gen/toir.c b/gen/toir.c index c0ea4c96..275d2ba7 100644 --- a/gen/toir.c +++ b/gen/toir.c @@ -118,8 +118,10 @@ elem* VarExp::toElem(IRState* p) 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* AssignExp::toElem(IRState* p) 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(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 @@ elem* NewExp::toElem(IRState* p) 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* ArrayLengthExp::toElem(IRState* p) 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 @@ elem* AssertExp::toElem(IRState* p) 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; + + llvm::Value* loca = llvm::ConstantInt::get(llvm::Type::Int32Ty, loc.linnum, false); + LLVM_DtoAssert(u->getValue(), loca, m ? m->val : NULL); - std::vector 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)); - 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; } ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/gen/tollvm.c b/gen/tollvm.c index ae7b190c..5d32fc3a 100644 --- a/gen/tollvm.c +++ b/gen/tollvm.c @@ -997,3 +997,66 @@ void LLVM_DtoGiveArgumentStorage(elem* l) 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 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 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); +} + + + + + + + diff --git a/gen/tollvm.h b/gen/tollvm.h index a2fa1251..b0e50874 100644 --- a/gen/tollvm.h +++ b/gen/tollvm.h @@ -44,4 +44,9 @@ llvm::Value* LLVM_DtoGEPi(llvm::Value* ptr, unsigned i0, unsigned i1, const std: 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" diff --git a/lphobos/build.sh b/lphobos/build.sh index 6437ce24..38384169 100755 --- a/lphobos/build.sh +++ b/lphobos/build.sh @@ -9,14 +9,15 @@ fi # 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 diff --git a/lphobos/internal/mem.d b/lphobos/internal/mem.d new file mode 100644 index 00000000..7b851634 --- /dev/null +++ b/lphobos/internal/mem.d @@ -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); +} diff --git a/test/arrays3.d b/test/arrays3.d new file mode 100644 index 00000000..9a68c055 --- /dev/null +++ b/test/arrays3.d @@ -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);} +} diff --git a/test/bug7.d b/test/bug7.d new file mode 100644 index 00000000..9dd22f57 --- /dev/null +++ b/test/bug7.d @@ -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(); +} diff --git a/test/foreach2.d b/test/foreach2.d new file mode 100644 index 00000000..c5d95342 --- /dev/null +++ b/test/foreach2.d @@ -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); + } +} diff --git a/test/foreach3.d b/test/foreach3.d new file mode 100644 index 00000000..5cf460d9 --- /dev/null +++ b/test/foreach3.d @@ -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"); +} diff --git a/test/memory1.d b/test/memory1.d new file mode 100644 index 00000000..9cdaccad --- /dev/null +++ b/test/memory1.d @@ -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);} +} diff --git a/test/throw1.d b/test/throw1.d new file mode 100644 index 00000000..2a45610d --- /dev/null +++ b/test/throw1.d @@ -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; +}