Commit 0bdc0bb534

Parker Liu <flyfish30@users.noreply.github.com>
2025-03-31 19:22:03
translate-c: fix referencing extern locals from nested blocks
1 parent 0753af7
Changed files (3)
lib
src
test
cases
lib/compiler/aro_translate_c.zig
@@ -1620,7 +1620,11 @@ pub fn ScopeExtra(comptime ScopeExtraContext: type, comptime ScopeExtraType: typ
                 .root => null,
                 .block => ret: {
                     const block = @as(*Block, @fieldParentPtr("base", scope));
-                    break :ret block.getLocalExternAlias(name);
+                    const alias_name = block.getLocalExternAlias(name);
+                    if (alias_name) |_alias_name| {
+                        break :ret _alias_name;
+                    }
+                    break :ret scope.parent.?.getLocalExternAlias(name);
                 },
                 .loop, .do_loop, .condition => scope.parent.?.getLocalExternAlias(name),
             };
src/translate_c.zig
@@ -1964,7 +1964,14 @@ fn transImplicitCastExpr(
                 return maybeSuppressResult(c, result_used, sub_expr_node);
             }
 
-            const addr = try Tag.address_of.create(c.arena, sub_expr_node);
+            const index_val = try Tag.integer_literal.create(c.arena, "0");
+            const index = try Tag.as.create(c.arena, .{
+                .lhs = try Tag.type.create(c.arena, "usize"),
+                .rhs = try Tag.int_cast.create(c.arena, index_val),
+            });
+            const array0_node = try Tag.array_access.create(c.arena, .{ .lhs = sub_expr_node, .rhs = index });
+            // Convert array to pointer by expression: addr = &sub_expr[0]
+            const addr = try Tag.address_of.create(c.arena, array0_node);
             const casted = try transCPtrCast(c, scope, expr.getBeginLoc(), dest_type, src_type, addr);
             return maybeSuppressResult(c, result_used, casted);
         },
test/cases/run_translated_c/sub_scope_extern_local_var_ref.c
@@ -0,0 +1,23 @@
+#include <stdlib.h>
+int a = 42;
+int foo(int bar) {
+    extern int a;
+    if (bar) {
+        return a;
+    }
+    return 0;
+}
+int main() {
+    int result1 = foo(0);
+    if (result1 != 0) abort();
+    int result2 = foo(1);
+    if (result2 != 42) abort();
+    a = 100;
+    int result3 = foo(1);
+    if (result3 != 100) abort();
+    return 0;
+}
+
+// run-translated-c
+// c_frontend=clang
+// link_libc=true