| ... | ... | @@ -439,6 +439,24 @@ pub fn translate( |
| 439 | 439 | return ast.render(gpa, context.global_scope.nodes.items); |
| 440 | 440 | } |
| 441 | 441 | |
| 442 | /// Determines whether macro is of the form: `#define FOO FOO` (Possibly with trailing tokens) |
| 443 | /// Macros of this form will not be translated. |
| 444 | fn isSelfDefinedMacro(unit: *const clang.ASTUnit, c: *const Context, macro: *const clang.MacroDefinitionRecord) bool { |
| 445 | const source = getMacroText(unit, c, macro); |
| 446 | var tokenizer = std.c.Tokenizer{ |
| 447 | .buffer = source, |
| 448 | }; |
| 449 | const name_tok = tokenizer.next(); |
| 450 | const name = source[name_tok.start..name_tok.end]; |
| 451 | |
| 452 | const first_tok = tokenizer.next(); |
| 453 | // We do not just check for `.Identifier` below because keyword tokens are preferentially matched first by |
| 454 | // the tokenizer. |
| 455 | // In other words we would miss `#define inline inline` (`inline` is a valid c89 identifier) |
| 456 | if (first_tok.id == .Eof) return false; |
| 457 | return mem.eql(u8, name, source[first_tok.start..first_tok.end]); |
| 458 | } |
| 459 | |
| 442 | 460 | fn prepopulateGlobalNameTable(ast_unit: *clang.ASTUnit, c: *Context) !void { |
| 443 | 461 | if (!ast_unit.visitLocalTopLevelDecls(c, declVisitorNamesOnlyC)) { |
| 444 | 462 | return error.OutOfMemory; |
| ... | ... | @@ -455,7 +473,10 @@ fn prepopulateGlobalNameTable(ast_unit: *clang.ASTUnit, c: *Context) !void { |
| 455 | 473 | const macro = @ptrCast(*clang.MacroDefinitionRecord, entity); |
| 456 | 474 | const raw_name = macro.getName_getNameStart(); |
| 457 | 475 | const name = try c.str(raw_name); |
| 458 | | try c.global_names.put(c.gpa, name, {}); |
| 476 | |
| 477 | if (!isSelfDefinedMacro(ast_unit, c, macro)) { |
| 478 | try c.global_names.put(c.gpa, name, {}); |
| 479 | } |
| 459 | 480 | }, |
| 460 | 481 | else => {}, |
| 461 | 482 | } |
| ... | ... | @@ -5446,6 +5467,16 @@ fn tokenizeMacro(source: []const u8, tok_list: *std.ArrayList(CToken)) Error!voi |
| 5446 | 5467 | } |
| 5447 | 5468 | } |
| 5448 | 5469 | |
| 5470 | fn getMacroText(unit: *const clang.ASTUnit, c: *const Context, macro: *const clang.MacroDefinitionRecord) []const u8 { |
| 5471 | const begin_loc = macro.getSourceRange_getBegin(); |
| 5472 | const end_loc = clang.Lexer.getLocForEndOfToken(macro.getSourceRange_getEnd(), c.source_manager, unit); |
| 5473 | |
| 5474 | const begin_c = c.source_manager.getCharacterData(begin_loc); |
| 5475 | const end_c = c.source_manager.getCharacterData(end_loc); |
| 5476 | const slice_len = @ptrToInt(end_c) - @ptrToInt(begin_c); |
| 5477 | return begin_c[0..slice_len]; |
| 5478 | } |
| 5479 | |
| 5449 | 5480 | fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void { |
| 5450 | 5481 | // TODO if we see #undef, delete it from the table |
| 5451 | 5482 | var it = unit.getLocalPreprocessingEntities_begin(); |
| ... | ... | @@ -5462,22 +5493,18 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void { |
| 5462 | 5493 | const macro = @ptrCast(*clang.MacroDefinitionRecord, entity); |
| 5463 | 5494 | const raw_name = macro.getName_getNameStart(); |
| 5464 | 5495 | const begin_loc = macro.getSourceRange_getBegin(); |
| 5465 | | const end_loc = clang.Lexer.getLocForEndOfToken(macro.getSourceRange_getEnd(), c.source_manager, unit); |
| 5466 | 5496 | |
| 5467 | 5497 | const name = try c.str(raw_name); |
| 5468 | 5498 | if (scope.containsNow(name)) { |
| 5469 | 5499 | continue; |
| 5470 | 5500 | } |
| 5471 | 5501 | |
| 5472 | | const begin_c = c.source_manager.getCharacterData(begin_loc); |
| 5473 | | const end_c = c.source_manager.getCharacterData(end_loc); |
| 5474 | | const slice_len = @ptrToInt(end_c) - @ptrToInt(begin_c); |
| 5475 | | const slice = begin_c[0..slice_len]; |
| 5502 | const source = getMacroText(unit, c, macro); |
| 5476 | 5503 | |
| 5477 | | try tokenizeMacro(slice, &tok_list); |
| 5504 | try tokenizeMacro(source, &tok_list); |
| 5478 | 5505 | |
| 5479 | 5506 | var macro_ctx = MacroCtx{ |
| 5480 | | .source = slice, |
| 5507 | .source = source, |
| 5481 | 5508 | .list = tok_list.items, |
| 5482 | 5509 | .name = name, |
| 5483 | 5510 | .loc = begin_loc, |
| ... | ... | @@ -5490,7 +5517,8 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void { |
| 5490 | 5517 | // if it equals itself, ignore. for example, from stdio.h: |
| 5491 | 5518 | // #define stdin stdin |
| 5492 | 5519 | const tok = macro_ctx.list[1]; |
| 5493 | | if (mem.eql(u8, name, slice[tok.start..tok.end])) { |
| 5520 | if (mem.eql(u8, name, source[tok.start..tok.end])) { |
| 5521 | assert(!c.global_names.contains(source[tok.start..tok.end])); |
| 5494 | 5522 | continue; |
| 5495 | 5523 | } |
| 5496 | 5524 | }, |