changeset 1411:e57859ca8f1e

Fix `scope(exit) foreach (ref v; arr) foo(v);`
author Frits van Bommel <fvbommel wxs.nl>
date Fri, 22 May 2009 21:38:01 +0200
parents cc2d8a7388c7
children 3f5ea912149d
files gen/llvmhelpers.cpp tests/mini/compile_scope_exit_foreach.d
diffstat 2 files changed, 28 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/gen/llvmhelpers.cpp	Fri May 22 13:17:06 2009 +0200
+++ b/gen/llvmhelpers.cpp	Fri May 22 21:38:01 2009 +0200
@@ -1055,8 +1055,20 @@
     {
         // 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());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/mini/compile_scope_exit_foreach.d	Fri May 22 21:38:01 2009 +0200
@@ -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;
+}