| ... | @@ -83,6 +83,7 @@ const Scope = struct { | ... | @@ -83,6 +83,7 @@ const Scope = struct { |
| 83 | } | 83 | } |
| 84 | | 84 | |
| 85 | /// Given the desired name, return a name that does not shadow anything from outer scopes. | 85 | /// Given the desired name, return a name that does not shadow anything from outer scopes. |
| | 86 | /// Inserts the returned name into the scope. |
| 86 | fn makeMangledName(scope: *Block, c: *Context, name: []const u8) ![]const u8 { | 87 | fn makeMangledName(scope: *Block, c: *Context, name: []const u8) ![]const u8 { |
| 87 | var proposed_name = name; | 88 | var proposed_name = name; |
| 88 | while (scope.contains(proposed_name)) { | 89 | while (scope.contains(proposed_name)) { |
| ... | @@ -136,15 +137,37 @@ const Scope = struct { | ... | @@ -136,15 +137,37 @@ const Scope = struct { |
| 136 | }; | 137 | }; |
| 137 | } | 138 | } |
| 138 | | 139 | |
| 139 | fn localContains(scope: *Root, name: []const u8) bool { | 140 | /// Given the desired name, return a name that does not shadow anything from outer scopes. |
| 140 | return scope.sym_table.contains(name) or | 141 | /// Inserts the returned name into the scope. |
| | 142 | /// Will allow `name` to be one of the preprocessed decl or macro names, but will not |
| | 143 | /// choose a mangled name that matches one of those. |
| | 144 | fn makeMangledName(scope: *Root, name: []const u8) ![]const u8 { |
| | 145 | if (!scope.containsNow(name)) { |
| | 146 | _ = try scope.context.global_names.put(name, {}); |
| | 147 | return name; |
| | 148 | } |
| | 149 | var proposed_name = name; |
| | 150 | while (scope.contains(proposed_name)) { |
| | 151 | proposed_name = try std.fmt.allocPrint(scope.context.a(), "{}_{}", .{ |
| | 152 | name, |
| | 153 | scope.context.getMangle(), |
| | 154 | }); |
| | 155 | } |
| | 156 | _ = try scope.context.global_names.put(proposed_name, {}); |
| | 157 | return proposed_name; |
| | 158 | } |
| | 159 | |
| | 160 | /// Check if the global scope contains this name, without looking into the "future", e.g. |
| | 161 | /// ignore the preprocessed decl and macro names. |
| | 162 | fn containsNow(scope: *Root, name: []const u8) bool { |
| | 163 | return isZigPrimitiveType(name) or |
| | 164 | scope.sym_table.contains(name) or |
| 141 | scope.macro_table.contains(name); | 165 | scope.macro_table.contains(name); |
| 142 | } | 166 | } |
| 143 | | 167 | |
| | 168 | /// Check if the global scope contains the name, includes all decls that haven't been translated yet. |
| 144 | fn contains(scope: *Root, name: []const u8) bool { | 169 | fn contains(scope: *Root, name: []const u8) bool { |
| 145 | return scope.localContains(name) or | 170 | return scope.containsNow(name) or scope.context.global_names.contains(name); |
| 146 | isZigPrimitiveType(name) or | | |
| 147 | scope.context.global_names.contains(name); | | |
| 148 | } | 171 | } |
| 149 | }; | 172 | }; |
| 150 | | 173 | |
| ... | @@ -308,9 +331,7 @@ pub fn translate( | ... | @@ -308,9 +331,7 @@ pub fn translate( |
| 308 | }; | 331 | }; |
| 309 | context.global_scope.* = Scope.Root.init(&context); | 332 | context.global_scope.* = Scope.Root.init(&context); |
| 310 | | 333 | |
| 311 | if (!ZigClangASTUnit_visitLocalTopLevelDecls(ast_unit, &context, declVisitorNamesOnlyC)) { | 334 | try prepopulateGlobalNameTable(ast_unit, &context); |
| 312 | return context.err; | | |
| 313 | } | | |
| 314 | | 335 | |
| 315 | if (!ZigClangASTUnit_visitLocalTopLevelDecls(ast_unit, &context, declVisitorC)) { | 336 | if (!ZigClangASTUnit_visitLocalTopLevelDecls(ast_unit, &context, declVisitorC)) { |
| 316 | return context.err; | 337 | return context.err; |
| ... | @@ -339,6 +360,29 @@ pub fn translate( | ... | @@ -339,6 +360,29 @@ pub fn translate( |
| 339 | return tree; | 360 | return tree; |
| 340 | } | 361 | } |
| 341 | | 362 | |
| | 363 | fn prepopulateGlobalNameTable(ast_unit: *ZigClangASTUnit, c: *Context) !void { |
| | 364 | if (!ZigClangASTUnit_visitLocalTopLevelDecls(ast_unit, c, declVisitorNamesOnlyC)) { |
| | 365 | return c.err; |
| | 366 | } |
| | 367 | |
| | 368 | // TODO if we see #undef, delete it from the table |
| | 369 | var it = ZigClangASTUnit_getLocalPreprocessingEntities_begin(ast_unit); |
| | 370 | const it_end = ZigClangASTUnit_getLocalPreprocessingEntities_end(ast_unit); |
| | 371 | |
| | 372 | while (it.I != it_end.I) : (it.I += 1) { |
| | 373 | const entity = ZigClangPreprocessingRecord_iterator_deref(it); |
| | 374 | switch (ZigClangPreprocessedEntity_getKind(entity)) { |
| | 375 | .MacroDefinitionKind => { |
| | 376 | const macro = @ptrCast(*ZigClangMacroDefinitionRecord, entity); |
| | 377 | const raw_name = ZigClangMacroDefinitionRecord_getName_getNameStart(macro); |
| | 378 | const name = try c.str(raw_name); |
| | 379 | _ = try c.global_names.put(name, {}); |
| | 380 | }, |
| | 381 | else => {}, |
| | 382 | } |
| | 383 | } |
| | 384 | } |
| | 385 | |
| 342 | extern fn declVisitorNamesOnlyC(context: ?*c_void, decl: *const ZigClangDecl) bool { | 386 | extern fn declVisitorNamesOnlyC(context: ?*c_void, decl: *const ZigClangDecl) bool { |
| 343 | const c = @ptrCast(*Context, @alignCast(@alignOf(Context), context)); | 387 | const c = @ptrCast(*Context, @alignCast(@alignOf(Context), context)); |
| 344 | declVisitorNamesOnly(c, decl) catch |err| { | 388 | declVisitorNamesOnly(c, decl) catch |err| { |
| ... | @@ -4272,7 +4316,7 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void { | ... | @@ -4272,7 +4316,7 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void { |
| 4272 | var it = ZigClangASTUnit_getLocalPreprocessingEntities_begin(unit); | 4316 | var it = ZigClangASTUnit_getLocalPreprocessingEntities_begin(unit); |
| 4273 | const it_end = ZigClangASTUnit_getLocalPreprocessingEntities_end(unit); | 4317 | const it_end = ZigClangASTUnit_getLocalPreprocessingEntities_end(unit); |
| 4274 | var tok_list = ctok.TokenList.init(c.a()); | 4318 | var tok_list = ctok.TokenList.init(c.a()); |
| 4275 | const scope = &c.global_scope.base; | 4319 | const scope = c.global_scope; |
| 4276 | | 4320 | |
| 4277 | while (it.I != it_end.I) : (it.I += 1) { | 4321 | while (it.I != it_end.I) : (it.I += 1) { |
| 4278 | const entity = ZigClangPreprocessingRecord_iterator_deref(it); | 4322 | const entity = ZigClangPreprocessingRecord_iterator_deref(it); |
| ... | @@ -4285,14 +4329,8 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void { | ... | @@ -4285,14 +4329,8 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void { |
| 4285 | | 4329 | |
| 4286 | const name = try c.str(raw_name); | 4330 | const name = try c.str(raw_name); |
| 4287 | | 4331 | |
| 4288 | // TODO https://github.com/ziglang/zig/issues/3756 | | |
| 4289 | // TODO https://github.com/ziglang/zig/issues/1802 | | |
| 4290 | const checked_name = if (isZigPrimitiveType(name)) try std.fmt.allocPrint(c.a(), "_{}", .{name}) else name; | | |
| 4291 | if (scope.contains(checked_name)) { | | |
| 4292 | continue; | | |
| 4293 | } | | |
| 4294 | const begin_c = ZigClangSourceManager_getCharacterData(c.source_manager, begin_loc); | 4332 | const begin_c = ZigClangSourceManager_getCharacterData(c.source_manager, begin_loc); |
| 4295 | ctok.tokenizeCMacro(c, begin_loc, checked_name, &tok_list, begin_c) catch |err| switch (err) { | 4333 | ctok.tokenizeCMacro(c, begin_loc, name, &tok_list, begin_c) catch |err| switch (err) { |
| 4296 | error.OutOfMemory => |e| return e, | 4334 | error.OutOfMemory => |e| return e, |
| 4297 | else => { | 4335 | else => { |
| 4298 | continue; | 4336 | continue; |
| ... | @@ -4307,7 +4345,7 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void { | ... | @@ -4307,7 +4345,7 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void { |
| 4307 | .Identifier => { | 4345 | .Identifier => { |
| 4308 | // if it equals itself, ignore. for example, from stdio.h: | 4346 | // if it equals itself, ignore. for example, from stdio.h: |
| 4309 | // #define stdin stdin | 4347 | // #define stdin stdin |
| 4310 | if (mem.eql(u8, checked_name, next.bytes)) { | 4348 | if (mem.eql(u8, name, next.bytes)) { |
| 4311 | continue; | 4349 | continue; |
| 4312 | } | 4350 | } |
| 4313 | }, | 4351 | }, |
| ... | @@ -4318,15 +4356,19 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void { | ... | @@ -4318,15 +4356,19 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void { |
| 4318 | }, | 4356 | }, |
| 4319 | else => {}, | 4357 | else => {}, |
| 4320 | } | 4358 | } |
| | 4359 | |
| | 4360 | // TODO https://github.com/ziglang/zig/issues/3756 |
| | 4361 | // TODO https://github.com/ziglang/zig/issues/1802 |
| | 4362 | const mangled_name = try scope.makeMangledName(name); |
| 4321 | const macro_fn = if (tok_it.peek().?.id == .Fn) blk: { | 4363 | const macro_fn = if (tok_it.peek().?.id == .Fn) blk: { |
| 4322 | _ = tok_it.next(); | 4364 | _ = tok_it.next(); |
| 4323 | break :blk true; | 4365 | break :blk true; |
| 4324 | } else false; | 4366 | } else false; |
| 4325 | | 4367 | |
| 4326 | (if (macro_fn) | 4368 | (if (macro_fn) |
| 4327 | transMacroFnDefine(c, &tok_it, checked_name, begin_loc) | 4369 | transMacroFnDefine(c, &tok_it, mangled_name, begin_loc) |
| 4328 | else | 4370 | else |
| 4329 | transMacroDefine(c, &tok_it, checked_name, begin_loc)) catch |err| switch (err) { | 4371 | transMacroDefine(c, &tok_it, mangled_name, begin_loc)) catch |err| switch (err) { |
| 4330 | error.ParseError => continue, | 4372 | error.ParseError => continue, |
| 4331 | error.OutOfMemory => |e| return e, | 4373 | error.OutOfMemory => |e| return e, |
| 4332 | }; | 4374 | }; |