diff options
| author | Evan Haas <evan@lagerdata.com> | 2021-08-31 12:23:23 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-09-01 17:54:07 -0700 |
| commit | df589eecd61a4a2c93922302f8f486f18d0ff06b (patch) | |
| tree | dffedae386db77c3a7beea33efbd91976679c324 /src | |
| parent | 8d2acff197a46a9de33ce78713291428aa45ee7c (diff) | |
| download | zig-df589eecd61a4a2c93922302f8f486f18d0ff06b.tar.gz zig-df589eecd61a4a2c93922302f8f486f18d0ff06b.zip | |
translate-c: improve handling of undefined identifiers
Diffstat (limited to 'src')
| -rw-r--r-- | src/translate_c.zig | 28 | ||||
| -rw-r--r-- | src/translate_c/ast.zig | 35 |
2 files changed, 33 insertions, 30 deletions
diff --git a/src/translate_c.zig b/src/translate_c.zig index d204f7177f..f95c18d8f1 100644 --- a/src/translate_c.zig +++ b/src/translate_c.zig @@ -395,7 +395,15 @@ pub fn translate( context.pattern_list.deinit(gpa); } - try context.global_scope.nodes.append(Tag.usingnamespace_builtins.init()); + inline for (meta.declarations(std.zig.c_builtins)) |decl| { + if (decl.is_pub) { + const builtin = try Tag.pub_var_simple.create(context.arena, .{ + .name = decl.name, + .init = try Tag.import_builtin.create(context.arena, decl.name), + }); + try context.global_scope.nodes.append(builtin); + } + } try prepopulateGlobalNameTable(ast_unit, &context); @@ -5249,16 +5257,19 @@ const MacroCtx = struct { return MacroSlicer{ .source = self.source, .tokens = self.list }; } - fn containsUndefinedIdentifier(self: *MacroCtx, scope: *Scope) ?[]const u8 { + fn containsUndefinedIdentifier(self: *MacroCtx, scope: *Scope, params: []const ast.Payload.Param) ?[]const u8 { const slicer = self.makeSlicer(); var i: usize = 1; // index 0 is the macro name while (i < self.list.len) : (i += 1) { const token = self.list[i]; switch (token.id) { - .Period => i += 1, // skip next token since field identifiers can be unknown + .Period, .Arrow => i += 1, // skip next token since field identifiers can be unknown .Identifier => { const identifier = slicer.slice(token); - if (!scope.contains(identifier)) return identifier; + const is_param = for (params) |param| { + if (param.name != null and mem.eql(u8, identifier, param.name.?)) break true; + } else false; + if (!scope.contains(identifier) and !isBuiltinDefined(identifier) and !is_param) return identifier; }, else => {}, } @@ -5361,7 +5372,7 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void { fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void { const scope = &c.global_scope.base; - if (m.containsUndefinedIdentifier(scope)) |ident| + if (m.containsUndefinedIdentifier(scope, &.{})) |ident| return m.fail(c, "unable to translate macro: undefined identifier `{s}`", .{ident}); const init_node = try parseCExpr(c, m, scope); @@ -5414,6 +5425,9 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void { return m.fail(c, "unable to translate C expr: expected ')'", .{}); } + if (m.containsUndefinedIdentifier(scope, fn_params.items)) |ident| + return m.fail(c, "unable to translate macro: undefined identifier `{s}`", .{ident}); + const expr = try parseCExpr(c, m, scope); const last = m.next().?; if (last != .Eof and last != .Nl) @@ -5755,10 +5769,6 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N }, .Identifier => { const mangled_name = scope.getAlias(slice); - if (mem.startsWith(u8, mangled_name, "__builtin_") and !isBuiltinDefined(mangled_name)) { - try m.fail(c, "TODO implement function '{s}' in std.zig.c_builtins", .{mangled_name}); - return error.ParseError; - } if (builtin_typedef_map.get(mangled_name)) |ty| return Tag.type.create(c.arena, ty); const identifier = try Tag.identifier.create(c.arena, mangled_name); scope.skipVariableDiscard(identifier.castTag(.identifier).?.data); diff --git a/src/translate_c/ast.zig b/src/translate_c/ast.zig index a77334e7d1..2bd9a0c791 100644 --- a/src/translate_c/ast.zig +++ b/src/translate_c/ast.zig @@ -31,8 +31,6 @@ pub const Node = extern union { @"anytype", @"continue", @"break", - /// pub usingnamespace @import("std").zig.c_builtins - usingnamespace_builtins, // After this, the tag requires a payload. integer_literal, @@ -119,6 +117,8 @@ pub const Node = extern union { ellipsis3, assign, + /// @import("std").zig.c_builtins.<name> + import_builtin, log2_int_type, /// @import("std").math.Log2Int(operand) std_math_Log2Int, @@ -224,7 +224,7 @@ pub const Node = extern union { /// [1]type{val} ** count array_filler, - pub const last_no_payload_tag = Tag.usingnamespace_builtins; + pub const last_no_payload_tag = Tag.@"break"; pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1; pub fn Type(comptime t: Tag) type { @@ -236,7 +236,6 @@ pub const Node = extern union { .true_literal, .false_literal, .empty_block, - .usingnamespace_builtins, .return_void, .zero_literal, .one_literal, @@ -344,6 +343,7 @@ pub const Node = extern union { .warning, .type, .helpers_macro, + .import_builtin, => Payload.Value, .discard => Payload.Discard, .@"if" => Payload.If, @@ -871,22 +871,6 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { try c.buf.append('\n'); return @as(NodeIndex, 0); // error: integer value 0 cannot be coerced to type 'std.mem.Allocator.Error!u32' }, - .usingnamespace_builtins => { - // pub usingnamespace @import("std").c.builtins; - _ = try c.addToken(.keyword_pub, "pub"); - const usingnamespace_token = try c.addToken(.keyword_usingnamespace, "usingnamespace"); - const import_node = try renderStdImport(c, &.{ "zig", "c_builtins" }); - _ = try c.addToken(.semicolon, ";"); - - return c.addNode(.{ - .tag = .@"usingnamespace", - .main_token = usingnamespace_token, - .data = .{ - .lhs = import_node, - .rhs = undefined, - }, - }); - }, .std_math_Log2Int => { const payload = node.castTag(.std_math_Log2Int).?.data; const import_node = try renderStdImport(c, &.{ "math", "Log2Int" }); @@ -1143,6 +1127,15 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { }; return renderStdImport(c, &chain); }, + .import_builtin => { + const payload = node.castTag(.import_builtin).?.data; + const chain = [_][]const u8{ + "zig", + "c_builtins", + payload, + }; + return renderStdImport(c, &chain); + }, .string_slice => { const payload = node.castTag(.string_slice).?.data; @@ -2352,7 +2345,6 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex { .@"comptime", .@"defer", .asm_simple, - .usingnamespace_builtins, .while_true, .if_not_break, .switch_else, @@ -2371,6 +2363,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex { .bit_xor_assign, .assign, .helpers_macro, + .import_builtin, => { // these should never appear in places where grouping might be needed. unreachable; |
