diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 910e785d..f8b8ae40 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -393,19 +393,7 @@ void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs, int op) Type* t2 = rhs->getType()->toBasetype(); if (t->ty == Tstruct) { - if (!stripModifiers(t)->equals(stripModifiers(t2))) { - // FIXME: use 'rhs' for something !?! - DtoAggrZeroInit(lhs->getLVal()); -#if DMDV2 - TypeStruct *ts = static_cast(lhs->getType()); - if (ts->sym->isNested() && ts->sym->vthis) - DtoResolveNestedContext(loc, ts->sym, lhs->getLVal()); -#endif - } - else { - DtoAggrCopy(lhs->getLVal(), rhs->getRVal()); - } - + DtoAggrCopy(lhs->getLVal(), rhs->getRVal()); } else if (t->ty == Tarray) { // lhs is slice diff --git a/gen/tocall.cpp b/gen/tocall.cpp index 0a83c0ec..5b6b4696 100644 --- a/gen/tocall.cpp +++ b/gen/tocall.cpp @@ -652,7 +652,39 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions* break; default: - assert(0 && "unhandled repainting of return value"); + // Unfortunately, DMD has quirks resp. bugs with regard to name + // mangling: For voldemort-type functions which return a nested + // struct, the mangled name of the return type changes during + // semantic analysis. + // + // (When the function deco is first computed as part of + // determining the return type deco, its return type part is + // left off to avoid cycles. If mangle/toDecoBuffer is then + // called again for the type, it will pick up the previous + // result and return the full deco string for the nested struct + // type, consisting of both the full mangled function name, and + // the struct identifier.) + // + // Thus, the type merging in stripModifiers does not work + // reliably, and the equality check above can fail even if the + // types only differ in a qualifier. + // + // Because a proper fix for this in the frontend is hard, we + // just carry on and hope that the frontend didn't mess up, + // i.e. that the LLVM types really match up. + // + // An example situation where this case occurs is: + // --- + // auto iota() { + // static struct Result { + // this(int) {} + // inout(Result) test() inout { return cast(inout)Result(0); } + // } + // return Result.init; + // } + // void main() { auto r = iota(); } + // --- + break; } if (Logger::enabled()) Logger::cout() << "final return value: " << *retllval << '\n'; diff --git a/gen/toir.cpp b/gen/toir.cpp index c348dd10..d5503094 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -607,10 +607,24 @@ DValue* AssignExp::toElem(IRState* p) } } - Logger::println("performing normal assignment"); - DValue* l = e1->toElem(p); DValue* r = e2->toElem(p); + + if (e1->type->toBasetype()->ty == Tstruct && e2->op == TOKint64) + { + Logger::println("performing aggregate zero initialization"); + assert(e2->toInteger() == 0); + DtoAggrZeroInit(l->getLVal()); +#if DMDV2 + TypeStruct *ts = static_cast(e1->type); + if (ts->sym->isNested() && ts->sym->vthis) + DtoResolveNestedContext(loc, ts->sym, l->getLVal()); +#endif + // Return value should be irrelevant. + return r; + } + + Logger::println("performing normal assignment"); DtoAssign(loc, l, r, op); if (l->isSlice())