aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEvan Haas <evan@lagerdata.com>2021-08-31 12:23:23 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-09-01 17:54:07 -0700
commitdf589eecd61a4a2c93922302f8f486f18d0ff06b (patch)
treedffedae386db77c3a7beea33efbd91976679c324 /src
parent8d2acff197a46a9de33ce78713291428aa45ee7c (diff)
downloadzig-df589eecd61a4a2c93922302f8f486f18d0ff06b.tar.gz
zig-df589eecd61a4a2c93922302f8f486f18d0ff06b.zip
translate-c: improve handling of undefined identifiers
Diffstat (limited to 'src')
-rw-r--r--src/translate_c.zig28
-rw-r--r--src/translate_c/ast.zig35
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;