| ... | ... | @@ -139,7 +139,7 @@ pub fn translate( |
| 139 | 139 | // For memory that has the same lifetime as the Ast that we return |
| 140 | 140 | // from this function. |
| 141 | 141 | var arena_allocator = std.heap.ArenaAllocator.init(gpa); |
| 142 | | errdefer arena_allocator.deinit(); |
| 142 | defer arena_allocator.deinit(); |
| 143 | 143 | const arena = arena_allocator.allocator(); |
| 144 | 144 | |
| 145 | 145 | var context = Context{ |
| ... | ... | @@ -5497,6 +5497,7 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void { |
| 5497 | 5497 | const str_node = try Tag.string_literal.create(c.arena, "\"\""); |
| 5498 | 5498 | const var_decl = try Tag.pub_var_simple.create(c.arena, .{ .name = name, .init = str_node }); |
| 5499 | 5499 | try c.global_scope.macro_table.put(name, var_decl); |
| 5500 | try c.global_scope.blank_macros.put(name, {}); |
| 5500 | 5501 | continue; |
| 5501 | 5502 | }, |
| 5502 | 5503 | .LParen => { |
| ... | ... | @@ -5527,6 +5528,29 @@ fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void { |
| 5527 | 5528 | .invalid_arg_usage => unreachable, // no args |
| 5528 | 5529 | }; |
| 5529 | 5530 | |
| 5531 | // Check if the macro only uses other blank macros. |
| 5532 | while (true) { |
| 5533 | switch (m.peek().?) { |
| 5534 | .Identifier => { |
| 5535 | const tok = m.list[m.i + 1]; |
| 5536 | const slice = m.source[tok.start..tok.end]; |
| 5537 | if (c.global_scope.blank_macros.contains(slice)) { |
| 5538 | m.i += 1; |
| 5539 | continue; |
| 5540 | } |
| 5541 | }, |
| 5542 | .Eof, .Nl => { |
| 5543 | try c.global_scope.blank_macros.put(m.name, {}); |
| 5544 | const init_node = try Tag.string_literal.create(c.arena, "\"\""); |
| 5545 | const var_decl = try Tag.pub_var_simple.create(c.arena, .{ .name = m.name, .init = init_node }); |
| 5546 | try c.global_scope.macro_table.put(m.name, var_decl); |
| 5547 | return; |
| 5548 | }, |
| 5549 | else => {}, |
| 5550 | } |
| 5551 | break; |
| 5552 | } |
| 5553 | |
| 5530 | 5554 | const init_node = try parseCExpr(c, m, scope); |
| 5531 | 5555 | const last = m.next().?; |
| 5532 | 5556 | if (last != .Eof and last != .Nl) |
| ... | ... | @@ -5960,6 +5984,9 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N |
| 5960 | 5984 | return parseCNumLit(c, m); |
| 5961 | 5985 | }, |
| 5962 | 5986 | .Identifier => { |
| 5987 | if (c.global_scope.blank_macros.contains(slice)) { |
| 5988 | return parseCPrimaryExprInner(c, m, scope); |
| 5989 | } |
| 5963 | 5990 | const mangled_name = scope.getAlias(slice); |
| 5964 | 5991 | if (builtin_typedef_map.get(mangled_name)) |ty| return Tag.type.create(c.arena, ty); |
| 5965 | 5992 | const identifier = try Tag.identifier.create(c.arena, mangled_name); |
| ... | ... | @@ -5992,10 +6019,19 @@ fn parseCPrimaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 5992 | 6019 | // after a primary expression. |
| 5993 | 6020 | while (true) { |
| 5994 | 6021 | switch (m.peek().?) { |
| 5995 | | .StringLiteral, .Identifier => {}, |
| 6022 | .StringLiteral => {}, |
| 6023 | .Identifier => { |
| 6024 | const tok = m.list[m.i + 1]; |
| 6025 | const slice = m.source[tok.start..tok.end]; |
| 6026 | if (c.global_scope.blank_macros.contains(slice)) { |
| 6027 | m.i += 1; |
| 6028 | continue; |
| 6029 | } |
| 6030 | }, |
| 5996 | 6031 | else => break, |
| 5997 | 6032 | } |
| 5998 | | node = try Tag.array_cat.create(c.arena, .{ .lhs = node, .rhs = try parseCPrimaryExprInner(c, m, scope) }); |
| 6033 | const rhs = try parseCPrimaryExprInner(c, m, scope); |
| 6034 | node = try Tag.array_cat.create(c.arena, .{ .lhs = node, .rhs = rhs }); |
| 5999 | 6035 | } |
| 6000 | 6036 | return node; |
| 6001 | 6037 | } |
| ... | ... | @@ -6211,7 +6247,24 @@ fn parseCCastExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6211 | 6247 | switch (m.next().?) { |
| 6212 | 6248 | .LParen => { |
| 6213 | 6249 | if (try parseCTypeName(c, m, scope, true)) |type_name| { |
| 6214 | | try m.skip(c, .RParen); |
| 6250 | while (true) { |
| 6251 | const next_token = m.next().?; |
| 6252 | switch (next_token) { |
| 6253 | .RParen => break, |
| 6254 | else => |next_tag| { |
| 6255 | // Skip trailing blank defined before the RParen. |
| 6256 | if (next_tag == .Identifier and c.global_scope.blank_macros.contains(m.slice())) { |
| 6257 | continue; |
| 6258 | } |
| 6259 | try m.fail( |
| 6260 | c, |
| 6261 | "unable to translate C expr: expected ')' instead got '{s}'", |
| 6262 | .{next_token.symbol()}, |
| 6263 | ); |
| 6264 | return error.ParseError; |
| 6265 | }, |
| 6266 | } |
| 6267 | } |
| 6215 | 6268 | if (m.peek().? == .LBrace) { |
| 6216 | 6269 | // initializer list |
| 6217 | 6270 | return parseCPostfixExpr(c, m, scope, type_name); |
| ... | ... | @@ -6239,6 +6292,9 @@ fn parseCSpecifierQualifierList(c: *Context, m: *MacroCtx, scope: *Scope, allow_ |
| 6239 | 6292 | const tok = m.next().?; |
| 6240 | 6293 | switch (tok) { |
| 6241 | 6294 | .Identifier => { |
| 6295 | if (c.global_scope.blank_macros.contains(m.slice())) { |
| 6296 | return try parseCSpecifierQualifierList(c, m, scope, allow_fail); |
| 6297 | } |
| 6242 | 6298 | const mangled_name = scope.getAlias(m.slice()); |
| 6243 | 6299 | if (!allow_fail or c.typedefs.contains(mangled_name)) { |
| 6244 | 6300 | if (builtin_typedef_map.get(mangled_name)) |ty| return try Tag.type.create(c.arena, ty); |