diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 6b823fc5..2edf5ac1 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -1055,8 +1055,20 @@ LLValue* DtoRawVarDeclaration(VarDeclaration* var, LLValue* addr) { // if this already has storage, it must've been handled already if (var->ir.irLocal && var->ir.irLocal->value) { - assert(!addr || addr == var->ir.irLocal->value); - return var->ir.irLocal->value; + if (addr && addr != var->ir.irLocal->value) { + // This can happen, for example, in scope(exit) blocks which + // are translated to IR multiple times. + // That *should* only happen after the first one is completely done + // though, so just set the address. + IF_LOG { + Logger::println("Replacing LLVM address of %s", var->toChars()); + LOG_SCOPE; + Logger::cout() << "Old val: " << *var->ir.irLocal->value << '\n'; + Logger::cout() << "New val: " << *addr << '\n'; + } + var->ir.irLocal->value = addr; + } + return addr; } assert(!var->ir.isSet()); diff --git a/tests/mini/compile_scope_exit_foreach.d b/tests/mini/compile_scope_exit_foreach.d new file mode 100644 index 00000000..201f097a --- /dev/null +++ b/tests/mini/compile_scope_exit_foreach.d @@ -0,0 +1,14 @@ +module scope_exit_foreach; + +void bar(size_t); + +long foo(ubyte[] arr) { + scope(exit) { + foreach (ref b; arr) { + bar(b); + } + } + if (arr.length == 3) + return 0; + return arr.length; +}