diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index 84c3cbeaa98275869d7e6b454d257da93a411b48..4da3541db9d6480a0bcd667b7ff42223c44907ee 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -122,6 +122,7 @@ const Scope = struct { base: Scope, sym_table: SymbolTable, macro_table: SymbolTable, + context: *Context, fn init(c: *Context) Root { return .{ @@ -131,14 +132,20 @@ const Scope = struct { }, .sym_table = SymbolTable.init(c.a()), .macro_table = SymbolTable.init(c.a()), + .context = c, }; } - fn contains(scope: *Root, name: []const u8) bool { - return isZigPrimitiveType(name) or - scope.sym_table.contains(name) or + fn localContains(scope: *Root, name: []const u8) bool { + return scope.sym_table.contains(name) or scope.macro_table.contains(name); } + + fn contains(scope: *Root, name: []const u8) bool { + return scope.localContains(name) or + isZigPrimitiveType(name) or + scope.context.global_names.contains(name); + } }; fn findBlockScope(inner: *Scope, c: *Context) !*Scope.Block { @@ -207,6 +214,12 @@ pub const Context = struct { clang_context: *ZigClangASTContext, mangle_count: u32 = 0, + /// This one is different than the root scope's name table. This contains + /// a list of names that we found by visiting all the top level decls without + /// translating them. The other maps are updated as we translate; this one is updated + /// up front in a pre-processing step. + global_names: std.StringHashMap(void), + fn getMangle(c: *Context) u32 { c.mangle_count += 1; return c.mangle_count; @@ -291,9 +304,14 @@ pub fn translate( .alias_list = AliasList.init(arena), .global_scope = try arena.create(Scope.Root), .clang_context = ZigClangASTUnit_getASTContext(ast_unit).?, + .global_names = std.StringHashMap(void).init(arena), }; context.global_scope.* = Scope.Root.init(&context); + if (!ZigClangASTUnit_visitLocalTopLevelDecls(ast_unit, &context, declVisitorNamesOnlyC)) { + return context.err; + } + if (!ZigClangASTUnit_visitLocalTopLevelDecls(ast_unit, &context, declVisitorC)) { return context.err; } @@ -321,6 +339,15 @@ pub fn translate( return tree; } +extern fn declVisitorNamesOnlyC(context: ?*c_void, decl: *const ZigClangDecl) bool { + const c = @ptrCast(*Context, @alignCast(@alignOf(Context), context)); + declVisitorNamesOnly(c, decl) catch |err| { + c.err = err; + return false; + }; + return true; +} + extern fn declVisitorC(context: ?*c_void, decl: *const ZigClangDecl) bool { const c = @ptrCast(*Context, @alignCast(@alignOf(Context), context)); declVisitor(c, decl) catch |err| { @@ -330,6 +357,11 @@ extern fn declVisitorC(context: ?*c_void, decl: *const ZigClangDecl) bool { return true; } +fn declVisitorNamesOnly(c: *Context, decl: *const ZigClangDecl) Error!void { + const decl_name = try c.str(ZigClangDecl_getName_bytes_begin(decl)); + _ = try c.global_names.put(decl_name, {}); +} + fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void { switch (ZigClangDecl_getKind(decl)) { .Function => { diff --git a/test/translate_c.zig b/test/translate_c.zig index 96e9a9a65c699cfaf98c2f8d07e0b73894f8ee8f..0dec1d1b72bee700daa5707f7842bfe3efd5c67d 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -2275,4 +2275,17 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ return @bitCast(c_ushort, @truncate(c_short, x)); \\} }); + + cases.add("arg name aliasing decl which comes after", + \\int foo(int bar) { + \\ bar = 2; + \\} + \\int bar = 4; + , &[_][]const u8{ + \\pub export fn foo(arg_bar_1: c_int) c_int { + \\ var bar_1 = arg_bar_1; + \\ bar_1 = 2; + \\} + \\pub export var bar: c_int = 4; + }); }