From daad516579fcc4a52c3e603142aafe893fed3d55 Mon Sep 17 00:00:00 2001 From: Tomas Lindquist Olsen Date: Mon, 4 Aug 2008 02:59:34 +0200 Subject: [PATCH] Removed the 'needsstorage' thing from Dsymbol. Arguments are not always given storage when applicable. This is not longer treat specially in this regard. Code for accessing nested variables and contexts rewritten. Probably more. Fairly well tested. --- dmd/declaration.c | 5 - dmd/declaration.h | 3 - dmd/expression.c | 6 - dmd/func.c | 5 - gen/aa.cpp | 4 - gen/d-asm-i386.h | 3 - gen/dvalue.cpp | 2 +- gen/dvalue.h | 9 -- gen/functions.cpp | 61 ++++----- gen/llvmhelpers.cpp | 280 +++++++++++++++++++----------------------- gen/llvmhelpers.h | 2 +- gen/toir.cpp | 28 ++--- tests/mini/foreach9.d | 24 ++++ tests/mini/nested15.d | 35 ++++++ tests/mini/nested5.d | 5 +- tests/mini/nested6a.d | 17 +-- tests/runminitest.d | 2 + 17 files changed, 232 insertions(+), 259 deletions(-) create mode 100644 tests/mini/foreach9.d create mode 100644 tests/mini/nested15.d diff --git a/dmd/declaration.c b/dmd/declaration.c index 5015b7f0..62b1c8b2 100644 --- a/dmd/declaration.c +++ b/dmd/declaration.c @@ -621,9 +621,6 @@ VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer onstack = 0; canassign = 0; value = NULL; - - // LLVMDC - needsStorage = false; } Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s) @@ -645,8 +642,6 @@ Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s) sv = new VarDeclaration(loc, type ? type->syntaxCopy() : NULL, ident, init); sv->storage_class = storage_class; - // LLVMDC - sv->needsStorage = needsStorage; } #ifdef _DH // Syntax copy for header file diff --git a/dmd/declaration.h b/dmd/declaration.h index 00a70761..32103da2 100644 --- a/dmd/declaration.h +++ b/dmd/declaration.h @@ -266,9 +266,6 @@ struct VarDeclaration : Declaration // Eliminate need for dynamic_cast VarDeclaration *isVarDeclaration() { return (VarDeclaration *)this; } - - // LLVMDC - bool needsStorage; }; /**************************************************************/ diff --git a/dmd/expression.c b/dmd/expression.c index bf1665b7..362a11d4 100644 --- a/dmd/expression.c +++ b/dmd/expression.c @@ -3628,7 +3628,6 @@ Expression *SymOffExp::semantic(Scope *sc) if (v) { v->checkNestedReference(sc, loc); - v->needsStorage = true; } return this; } @@ -3777,7 +3776,6 @@ Expression *VarExp::modifiableLvalue(Scope *sc, Expression *e) if (v && v->canassign == 0 && (var->isConst() || (global.params.Dversion > 1 && var->isFinal()))) error("cannot modify final variable '%s'", var->toChars()); - v->needsStorage = true; if (var->isCtorinit()) { // It's only modifiable if inside the right constructor @@ -5991,10 +5989,6 @@ Expression *AddrExp::semantic(Scope *sc) e = e->semantic(sc); return e; } - else if (v) - { - v->needsStorage = true; - } } else if (e1->op == TOKarray) { diff --git a/dmd/func.c b/dmd/func.c index 8ffdfdd4..6ed927fa 100644 --- a/dmd/func.c +++ b/dmd/func.c @@ -796,11 +796,6 @@ void FuncDeclaration::semantic3(Scope *sc) if (v->storage_class & STClazy) v->storage_class |= STCin; v->semantic(sc2); - #if IN_LLVM - // LLVMDC: the argument needs an addres if we want to attach debug info to it. - if (global.params.symdebug) - v->needsStorage = true; - #endif if (!sc2->insert(v)) error("parameter %s.%s is already defined", toChars(), v->toChars()); else diff --git a/gen/aa.cpp b/gen/aa.cpp index f8eae571..9e1d214b 100644 --- a/gen/aa.cpp +++ b/gen/aa.cpp @@ -22,10 +22,6 @@ static LLValue* to_pkey(Loc& loc, DValue* key) if (key->isIm()) { pkey = key->getRVal(); } - else if (key->isThis()) { - pkey = key->getRVal(); - needmem = true; - } else if (DVarValue* var = key->isVar()) { if (var->lval) { pkey = key->getLVal(); diff --git a/gen/d-asm-i386.h b/gen/d-asm-i386.h index 6f8b6f1a..98d83917 100644 --- a/gen/d-asm-i386.h +++ b/gen/d-asm-i386.h @@ -2037,9 +2037,6 @@ struct AsmProcessor } } else if (exp->op == TOKvar) { VarDeclaration * v = ((VarExp *) exp)->var->isVarDeclaration(); - if (v) { - v->needsStorage = true; - } if (v && v->storage_class & STCfield) { operand->constDisplacement += v->offset; diff --git a/gen/dvalue.cpp b/gen/dvalue.cpp index 502921a9..7225ec20 100644 --- a/gen/dvalue.cpp +++ b/gen/dvalue.cpp @@ -53,7 +53,7 @@ LLValue* DVarValue::getRVal() else { if (rval) return rval; //Logger::cout() << "val: " << *val << '\n'; - if (!isThis() && !isField() && DtoCanLoad(val)) { + if (!isField() && DtoCanLoad(val)) { return DtoLoad(val); } return val; diff --git a/gen/dvalue.h b/gen/dvalue.h index 7964f7f8..ae42f72f 100644 --- a/gen/dvalue.h +++ b/gen/dvalue.h @@ -27,7 +27,6 @@ struct DConstValue; struct DNullValue; struct DVarValue; struct DFieldValue; -struct DThisValue; struct DFuncValue; struct DSliceValue; struct DArrayLenValue; @@ -49,7 +48,6 @@ struct DValue : Object virtual DNullValue* isNull() { return NULL; } virtual DVarValue* isVar() { return NULL; } virtual DFieldValue* isField() { return NULL; } - virtual DThisValue* isThis() { return NULL; } virtual DSliceValue* isSlice() { return NULL; } virtual DFuncValue* isFunc() { return NULL; } virtual DArrayLenValue* isArrayLen() { return NULL; } @@ -130,13 +128,6 @@ struct DFieldValue : DVarValue virtual DFieldValue* isField() { return this; } }; -// this d-value -struct DThisValue : DVarValue -{ - DThisValue(Type* t, VarDeclaration* vd, LLValue* llvmValue) : DVarValue(t, vd, llvmValue, true) {} - virtual DThisValue* isThis() { return this; } -}; - // slice d-value struct DSliceValue : DValue { diff --git a/gen/functions.cpp b/gen/functions.cpp index 6cf3af17..708de3b0 100644 --- a/gen/functions.cpp +++ b/gen/functions.cpp @@ -546,7 +546,8 @@ void DtoDefineFunc(FuncDeclaration* fd) Logger::println("Doing function body for: %s", fd->toChars()); assert(fd->ir.irFunc); - gIR->functions.push_back(fd->ir.irFunc); + IrFunction* irfunction = fd->ir.irFunc; + gIR->functions.push_back(irfunction); if (fd->isMain()) gIR->emitMain = true; @@ -562,7 +563,7 @@ void DtoDefineFunc(FuncDeclaration* fd) // create alloca point llvm::Instruction* allocaPoint = new llvm::AllocaInst(LLType::Int32Ty, "alloca point", beginbb); - gIR->func()->allocapoint = allocaPoint; + irfunction->allocapoint = allocaPoint; // debug info - after all allocas, but before any llvm.dbg.declare etc if (global.params.symdebug) DtoDwarfFuncStart(fd); @@ -574,18 +575,23 @@ void DtoDefineFunc(FuncDeclaration* fd) fd->vresult->ir.irLocal->value = new llvm::AllocaInst(DtoType(fd->vresult->type),"function_vresult",allocaPoint); } - // give 'this' argument debug info (and storage) - if (fd->needThis() && global.params.symdebug) + // give the 'this' argument storage and debug info + // only if not referenced by nested functions + if (fd->needThis() && !fd->vthis->nestedref) { - LLValue** thisvar = &fd->ir.irFunc->thisVar; - assert(*thisvar); - LLValue* thismem = new llvm::AllocaInst((*thisvar)->getType(), "newthis", allocaPoint); - DtoDwarfLocalVariable(thismem, fd->vthis); - gIR->ir->CreateStore(*thisvar, thismem); - *thisvar = thismem; + LLValue* thisvar = irfunction->thisVar; + assert(thisvar); + + LLValue* thismem = new llvm::AllocaInst(thisvar->getType(), ".newthis", allocaPoint); + DtoStore(thisvar, thismem); + irfunction->thisVar = thismem; + + if (global.params.symdebug) + DtoDwarfLocalVariable(thismem, fd->vthis); } // give arguments storage + // and debug info if (fd->parameters) { size_t n = fd->parameters->dim; @@ -595,44 +601,27 @@ void DtoDefineFunc(FuncDeclaration* fd) VarDeclaration* vd = argsym->isVarDeclaration(); assert(vd); + IrLocal* irloc = vd->ir.irLocal; + assert(irloc); + bool refoutlazy = vd->storage_class & (STCref | STCout | STClazy); - // FIXME: llvm seems to want an alloca/byval for debug info - if (!vd->needsStorage || vd->nestedref || refoutlazy) + if (vd->nestedref || refoutlazy) { - Logger::println("skipping arg storage for (%s) %s ", vd->loc.toChars(), vd->toChars()); continue; } - // static array params don't support debug info it seems - // probably because they're not passed byval - else if (vd->type->toBasetype()->ty == Tsarray) - { - Logger::println("skipping arg storage for static array (%s) %s ", vd->loc.toChars(), vd->toChars()); - continue; - } - // debug info for normal aggr params seem to work fine else if (DtoIsPassedByRef(vd->type)) { - Logger::println("skipping arg storage for aggregate (%s) %s ", vd->loc.toChars(), vd->toChars()); - LLValue* vdirval = vd->ir.getIrValue(); + LLValue* vdirval = irloc->value; if (global.params.symdebug && !(isaArgument(vdirval) && !isaArgument(vdirval)->hasByValAttr())) DtoDwarfLocalVariable(vdirval, vd); continue; } - LLValue* a = vd->ir.irLocal->value; - assert(a); - std::string s(a->getName()); - Logger::println("giving argument '%s' storage", s.c_str()); - s.append("_storage"); - - LLValue* v = new llvm::AllocaInst(a->getType(),s,allocaPoint); - - if (global.params.symdebug) - DtoDwarfLocalVariable(v, vd); - - gIR->ir->CreateStore(a,v); - vd->ir.irLocal->value = v; + LLValue* a = irloc->value; + LLValue* v = new llvm::AllocaInst(a->getType(), "."+a->getName(), allocaPoint); + DtoStore(a,v); + irloc->value = v; } } diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index ac389ce9..59fe2a20 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -330,181 +330,154 @@ void DtoLeaveMonitor(LLValue* v) // NESTED VARIABLE HELPERS ////////////////////////////////////////////////////////////////////////////////////////*/ -static const LLType* get_next_frame_ptr_type(Dsymbol* sc) +/* + +got: + + context pointer of 'this' function + + declaration for target context's function + +want: + + context pointer of target function in call chain + +*/ + +static LLValue* dive_into_nested(Dsymbol* from, LLValue* val) { - assert(sc->isFuncDeclaration() || sc->isClassDeclaration()); - Dsymbol* p = sc->toParent2(); - if (!p->isFuncDeclaration() && !p->isClassDeclaration()) - Logger::println("unexpected parent symbol found while resolving frame pointer - '%s' kind: '%s'", p->toChars(), p->kind()); - assert(p->isFuncDeclaration() || p->isClassDeclaration()); - if (FuncDeclaration* fd = p->isFuncDeclaration()) - { - LLValue* v = fd->ir.irFunc->nestedVar; - assert(v); - return v->getType(); - } - else if (ClassDeclaration* cd = p->isClassDeclaration()) - { - return DtoType(cd->type); - } - else - { - Logger::println("symbol: '%s' kind: '%s'", sc->toChars(), sc->kind()); - assert(0); - } -} + from = from->toParent2(); -////////////////////////////////////////////////////////////////////////////////////////// - -static LLValue* get_frame_ptr_impl(FuncDeclaration* func, Dsymbol* sc, LLValue* v) -{ - LOG_SCOPE; - if (sc == func) + // parent is a function + if (FuncDeclaration* f = from->isFuncDeclaration()) { - return v; - } - else if (FuncDeclaration* fd = sc->isFuncDeclaration()) - { - Logger::println("scope is function: %s", fd->toChars()); - - if (fd->toParent2() == func) + IrFunction* irfunc = f->ir.irFunc; + // parent has nested var struct + if (irfunc->nestedVar) { - if (!func->ir.irFunc->nestedVar) - return NULL; - return DtoBitCast(v, func->ir.irFunc->nestedVar->getType()); + return DtoBitCast(val, irfunc->nestedVar->getType()); } - - v = DtoBitCast(v, get_next_frame_ptr_type(fd)); - Logger::cout() << "v = " << *v << '\n'; - - if (fd->toParent2()->isFuncDeclaration()) + // parent has this argument + else if (irfunc->thisVar) { - v = DtoGEPi(v, 0,0, "tmp"); - v = DtoLoad(v); - } - else if (ClassDeclaration* cd = fd->toParent2()->isClassDeclaration()) - { - v = DtoGEPi(v,0,2+cd->vthis->ir.irField->index,"tmp"); - v = DtoLoad(v); + return DtoBitCast(val, irfunc->thisVar->getType()->getContainedType(0)); } + // none of the above, means no context is required, dummy. else { - assert(0); + return getNullPtr(getVoidPtrType()); } - return get_frame_ptr_impl(func, fd->toParent2(), v); } - else if (ClassDeclaration* cd = sc->isClassDeclaration()) + // parent is a class + else if (ClassDeclaration* c = from->isClassDeclaration()) { - Logger::println("scope is class: %s", cd->toChars()); - return get_frame_ptr_impl(func, cd->toParent2(), v); + return DtoBitCast(DtoLoad(val), DtoType(c->type)); } + // parent is not valid else { - Logger::println("symbol: '%s'", sc->toPrettyChars()); - assert(0); + assert(0 && "!(class|function)"); } } -////////////////////////////////////////////////////////////////////////////////////////// - -static LLValue* get_frame_ptr(FuncDeclaration* func) -{ - Logger::println("Resolving context pointer for nested function: '%s'", func->toPrettyChars()); - LOG_SCOPE; - IrFunction* irfunc = gIR->func(); - - // in the right scope already - if (func == irfunc->decl) - return irfunc->decl->ir.irFunc->nestedVar; - - // use the 'this' pointer - LLValue* ptr = irfunc->decl->ir.irFunc->thisVar; - assert(ptr); - - // return the fully resolved frame pointer - ptr = get_frame_ptr_impl(func, irfunc->decl, ptr); - if (ptr) Logger::cout() << "Found context!" << *ptr; - else Logger::cout() << "NULL context!\n"; - - return ptr; -} - -////////////////////////////////////////////////////////////////////////////////////////// - LLValue* DtoNestedContext(FuncDeclaration* func) { - // resolve frame ptr - LLValue* ptr = get_frame_ptr(func); - Logger::cout() << "Nested context ptr = "; - if (ptr) Logger::cout() << *ptr; - else Logger::cout() << "NULL"; - Logger::cout() << '\n'; - return ptr; -} - -////////////////////////////////////////////////////////////////////////////////////////// - -static void print_frame_worker(VarDeclaration* vd, Dsymbol* par) -{ - if (vd->toParent2() == par) - { - Logger::println("found: '%s' kind: '%s'", par->toChars(), par->kind()); - return; - } - - Logger::println("diving into: '%s' kind: '%s'", par->toChars(), par->kind()); + Logger::println("listing context frame list for funcdecl '%s'", func->toPrettyChars()); LOG_SCOPE; - print_frame_worker(vd, par->toParent2()); -} -////////////////////////////////////////////////////////////////////////////////////////// + int level = 0; -static void print_nested_frame_list(VarDeclaration* vd, Dsymbol* par) -{ - Logger::println("Frame pointer list for nested var: '%s'", vd->toPrettyChars()); - LOG_SCOPE; - if (vd->toParent2() != par) - print_frame_worker(vd, par); - else - Logger::println("Found at level 0"); - Logger::println("Done"); -} - -////////////////////////////////////////////////////////////////////////////////////////// - -LLValue* DtoNestedVariable(VarDeclaration* vd) -{ - // log the frame list IrFunction* irfunc = gIR->func(); - if (Logger::enabled()) - print_nested_frame_list(vd, irfunc->decl); + Dsymbol* current = irfunc->decl; - // resolve frame ptr - FuncDeclaration* func = vd->toParent2()->isFuncDeclaration(); - assert(func); - LLValue* ptr = DtoNestedContext(func); - assert(ptr && "nested var, but no context"); - - // if there is no nestedVar the context itself is what we're after - if (!func->ir.irFunc->nestedVar) + // this context ? + if (current == func) { - return ptr; + return irfunc->nestedVar; } - // handle a "normal" nested variable + // otherwise use the context argument + LLValue* val = dive_into_nested(current, irfunc->thisVar); + current = current->toParent2(); + assert(val); - // we must cast here to be sure. nested classes just have a void* - ptr = DtoBitCast(ptr, func->ir.irFunc->nestedVar->getType()); + for (;;) + { + Logger::cout() << "context: " << *val << '\n'; + Logger::println("(%d) looking in: %s (%s)", level, current->toPrettyChars(), current->kind()); + if (FuncDeclaration* f = current->isFuncDeclaration()) + { + if (f == func) + { + Logger::println("-> found <-"); + Logger::cout() << "-> val: " << *val << '\n'; + return val; + } + else + { + val = DtoLoad(DtoGEPi(val,0,0)); + } + } + else if (ClassDeclaration* c = current->isClassDeclaration()) + { + val = DtoLoad(DtoGEPi(val, 0, 2+c->vthis->ir.irField->index)); + val = dive_into_nested(current, val); + } + else + { + Logger::cout() << "val: " << *val << '\n'; + assert(0 && "!(class|function)"); + } + current = current->toParent2(); + ++level; + } - // index nested var and load (if necessary) - LLValue* v = DtoGEPi(ptr, 0, vd->ir.irLocal->nestedIndex, "tmp"); - // references must be loaded, for normal variables this IS already the variable storage!!! + assert(0); + return val; +} + +DValue* DtoNestedVariable(Type* astype, VarDeclaration* vd) +{ + IrFunction* irfunc = gIR->func(); + + // var parent (the scope we're looking for) + Dsymbol* varParent = vd->toParent2(); + + // on level 0 + if (varParent == irfunc->decl) + { + LLValue* nest = irfunc->nestedVar; + LLValue* v = DtoGEPi(nest, 0, vd->ir.irLocal->nestedIndex, "tmp"); + // references must be loaded to get the variable address + if (vd->isParameter() && (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type))) + v = DtoLoad(v); + return new DVarValue(astype, vd, v, true); + } + + // on level n != 0 + FuncDeclaration* varFunc = varParent->isFuncDeclaration(); + assert(varFunc); + + // get context of variable + LLValue* ctx = DtoNestedContext(varFunc); + + // if no local var, it's the context itself (class this) + if (!vd->ir.irLocal) + return new DImValue(astype, ctx); + + // extract variable + IrLocal* local = vd->ir.irLocal; + assert(local); + assert(local->nestedIndex >= 0); + LLValue* val = DtoGEPi(ctx, 0, local->nestedIndex); + + // references must be loaded to get the variable address if (vd->isParameter() && (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type))) - v = DtoLoad(v); + val = DtoLoad(val); - // log and return - Logger::cout() << "Nested var ptr = " << *v << '\n'; - return v; + Logger::cout() << "value: " << *val << '\n'; + + return new DVarValue(astype, vd, val, true); } /****************************************************************************************/ @@ -576,19 +549,12 @@ void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs) } else if (t->ty == Tclass) { assert(t2->ty == Tclass); - // assignment to this in constructor special case - if (lhs->isThis()) { - LLValue* tmp = rhs->getRVal(); - FuncDeclaration* fdecl = gIR->func()->decl; - // respecify the this param - if (!llvm::isa(fdecl->ir.irFunc->thisVar)) - fdecl->ir.irFunc->thisVar = new llvm::AllocaInst(tmp->getType(), "newthis", gIR->topallocapoint()); - DtoStore(tmp, fdecl->ir.irFunc->thisVar); - } - // regular class ref -> class ref assignment - else { - DtoStore(rhs->getRVal(), lhs->getLVal()); - } + LLValue* l = lhs->getLVal(); + LLValue* r = rhs->getRVal(); + Logger::cout() << "l : " << *l << '\n'; + Logger::cout() << "r : " << *r << '\n'; + r = DtoBitCast(r, l->getType()->getContainedType(0)); + DtoStore(r, l); } else if (t->iscomplex()) { assert(!lhs->isComplex()); @@ -1540,6 +1506,8 @@ LLValue* DtoBoolean(Loc& loc, DValue* dval) else if (ty == Tpointer || ty == Tclass) { LLValue* val = dval->getRVal(); LLValue* zero = LLConstant::getNullValue(val->getType()); + Logger::cout() << "val: " << *val << '\n'; + Logger::cout() << "zero: " << *zero << '\n'; return gIR->ir->CreateICmpNE(val, zero, "tmp"); } // dynamic array diff --git a/gen/llvmhelpers.h b/gen/llvmhelpers.h index 7b584863..9a3e8e2e 100644 --- a/gen/llvmhelpers.h +++ b/gen/llvmhelpers.h @@ -36,7 +36,7 @@ void DtoLeaveMonitor(LLValue* v); // nested variable/class helpers LLValue* DtoNestedContext(FuncDeclaration* func); -LLValue* DtoNestedVariable(VarDeclaration* vd); +DValue* DtoNestedVariable(Type* astype, VarDeclaration* vd); // basic operations void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs); diff --git a/gen/toir.cpp b/gen/toir.cpp index 6909d72a..ebe62b8f 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -106,7 +106,7 @@ DValue* VarExp::toElem(IRState* p) // nested variable else if (vd->nestedref) { Logger::println("nested variable"); - return new DVarValue(type, vd, DtoNestedVariable(vd), true); + return DtoNestedVariable(type, vd); } // function parameter else if (vd->isParameter()) { @@ -114,7 +114,7 @@ DValue* VarExp::toElem(IRState* p) FuncDeclaration* fd = vd->toParent2()->isFuncDeclaration(); if (fd && fd != p->func()->decl) { Logger::println("nested parameter"); - return new DVarValue(type, vd, DtoNestedVariable(vd), true); + return DtoNestedVariable(type, vd); } else if (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type) || llvm::isa(vd->ir.getIrValue())) { return new DVarValue(type, vd, vd->ir.getIrValue(), true); @@ -472,16 +472,7 @@ DValue* AssignExp::toElem(IRState* p) if (l->isSlice() || l->isComplex()) return l; - if (type->toBasetype()->ty == Tstruct && e2->type->isintegral()) - { - // handle struct = 0; - return l; - } - else - { - assert(type->equals(e2->type)); - return r; - } + return r; } ////////////////////////////////////////////////////////////////////////////////////////// @@ -986,25 +977,20 @@ DValue* ThisExp::toElem(IRState* p) { LLValue* v = p->func()->thisVar; assert(v); - return new DImValue(type, v); + return new DVarValue(type, v, true); } // regular this expr else if (VarDeclaration* vd = var->isVarDeclaration()) { LLValue* v; if (vd->toParent2() != p->func()->decl) { Logger::println("nested this exp"); - v = DtoLoad(DtoNestedVariable(vd)); + return DtoNestedVariable(type, vd); } else { Logger::println("normal this exp"); v = p->func()->decl->ir.irFunc->thisVar; - if (llvm::isa(v)) - v = DtoLoad(v); } - const LLType* t = DtoType(type); - if (v->getType() != t) - v = DtoBitCast(v, t); - return new DThisValue(type, vd, v); + return new DVarValue(type, vd, v, true); } // anything we're not yet handling ? @@ -1497,7 +1483,7 @@ DValue* DeleteExp::toElem(IRState* p) LLValue* rval = dval->getRVal(); DtoDeleteClass(rval); } - if (!dval->isThis() && dval->isVar() && dval->isVar()->lval) { + if (dval->isVar() && dval->isVar()->lval) { LLValue* lval = dval->getLVal(); DtoStore(llvm::Constant::getNullValue(lval->getType()->getContainedType(0)), lval); } diff --git a/tests/mini/foreach9.d b/tests/mini/foreach9.d new file mode 100644 index 00000000..c9c63607 --- /dev/null +++ b/tests/mini/foreach9.d @@ -0,0 +1,24 @@ +module mini.foreach9; +extern(C) int printf(char* str, ...); + +struct array2d(T) { + int test() { + printf("%p\n", cast(void*) this); + foreach (x; *this) { + printf("%p\n", cast(void*) this); + } + return true; + } + int opApply(int delegate(ref int) dg) { + int x; + return dg(x), 0; + } +} + +unittest { + array2d!(int) test; + test.test(); + //int i = 0; i /= i; +} + +void main() { } diff --git a/tests/mini/nested15.d b/tests/mini/nested15.d new file mode 100644 index 00000000..ca096b4f --- /dev/null +++ b/tests/mini/nested15.d @@ -0,0 +1,35 @@ +// $HeadURL: svn://svn.berlios.de/dstress/trunk/run/t/this_13_A.d $ +// $Date: 2006-12-31 20:59:08 +0100 (Sun, 31 Dec 2006) $ +// $Author: thomask $ + +// @author@ Frank Benoit +// @date@ 2006-10-09 +// @uri@ http://d.puremagic.com/issues/show_bug.cgi?id=419 +// @desc@ [Issue 419] New: Anonymous classes are not working. + +// added to mini to catch regressions earlier + +module mini.nested15; + +class I { + abstract void get( char[] s ); +} + +class C{ + void init(){ + I i = new class() I { + void get( char[] s ){ + func(); + } + }; + } + void func( ){ } +} + +int main(){ + C c = new C(); + c.init(); + + return 0; +} + diff --git a/tests/mini/nested5.d b/tests/mini/nested5.d index 47881999..890eda3a 100644 --- a/tests/mini/nested5.d +++ b/tests/mini/nested5.d @@ -11,12 +11,13 @@ void main() { void func() { - printf("Hello world %d\n", i++); + printf("Hello nested world %d\n", i++); //i++; } } - scope c = new C; + auto c = new C; c.func(); + printf("i = %d\n", i); assert(i == 44); } diff --git a/tests/mini/nested6a.d b/tests/mini/nested6a.d index 9b70419f..ba266c33 100644 --- a/tests/mini/nested6a.d +++ b/tests/mini/nested6a.d @@ -12,28 +12,31 @@ void main() int j; void func() { - int k; + int k; printf("C.func() %d\n", i++); class C2 { - int l; + int l; void func2() { + printf("in C2.func2()\n"); printf("C2.func2() %d\n", i++); } - int m; + int m; } { - scope c2 = new C2; + printf("new C2\n"); + auto c2 = new C2; + printf("C2.func2()\n"); c2.func2(); } - int n; + int n; } - int o; + int o; } - scope c = new C; + auto c = new C; c.func(); } diff --git a/tests/runminitest.d b/tests/runminitest.d index bd2fbcc5..223aa40d 100644 --- a/tests/runminitest.d +++ b/tests/runminitest.d @@ -55,6 +55,8 @@ int main(string[] args) cmd ~= v; } int cl = classify(testname); + if (cl == COMPILE || cl == NOCOMPILE) + cmd ~= " -c"; writefln(cmd); if (system(cmd) != 0) { if (cl != NOCOMPILE)