Commit a6960b89ed
Changed files (2)
src-self-hosted
test
src-self-hosted/translate_c.zig
@@ -371,13 +371,13 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void {
return visitFnDecl(c, @ptrCast(*const ZigClangFunctionDecl, decl));
},
.Typedef => {
- return resolveTypeDef(c, @ptrCast(*const ZigClangTypedefNameDecl, decl));
+ _ = try transTypeDef(c, @ptrCast(*const ZigClangTypedefNameDecl, decl));
},
.Enum => {
_ = try transEnumDecl(c, @ptrCast(*const ZigClangEnumDecl, decl));
},
.Record => {
- return resolveRecordDecl(c, @ptrCast(*const ZigClangRecordDecl, decl));
+ _ = try transRecordDecl(c, @ptrCast(*const ZigClangRecordDecl, decl));
},
.Var => {
return visitVarDecl(c, @ptrCast(*const ZigClangVarDecl, decl));
@@ -541,10 +541,9 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
return addTopLevelDecl(c, checked_name, &node.base);
}
-fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Error!void {
- if (c.decl_table.contains(
- @ptrToInt(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl)),
- )) return; // Avoid processing this decl twice
+fn transTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Error!?*ast.Node {
+ if (c.decl_table.get(@ptrToInt(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl)))) |kv|
+ return try transCreateNodeIdentifier(c, kv.value); // Avoid processing this decl twice
const rp = makeRestorePoint(c);
const visib_tok = try appendToken(c, .Keyword_pub, "pub");
const const_tok = try appendToken(c, .Keyword_const, "const");
@@ -558,29 +557,40 @@ fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Err
const typedef_loc = ZigClangTypedefNameDecl_getLocation(typedef_decl);
node.init_node = transQualType(rp, child_qt, typedef_loc) catch |err| switch (err) {
error.UnsupportedType => {
- return failDecl(c, typedef_loc, typedef_name, "unable to resolve typedef child type", .{});
+ try failDecl(c, typedef_loc, typedef_name, "unable to resolve typedef child type", .{});
+ return null;
},
error.OutOfMemory => |e| return e,
};
node.semicolon_token = try appendToken(c, .Semicolon, ";");
try addTopLevelDecl(c, typedef_name, &node.base);
+ return transCreateNodeIdentifier(c, typedef_name);
}
-fn resolveRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!void {
- if (c.decl_table.contains(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)))) return; // Avoid processing this decl twice
- const rp = makeRestorePoint(c);
-
- const bare_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, record_decl)));
+fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*ast.Node {
+ if (c.decl_table.get(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)))) |kv|
+ return try transCreateNodeIdentifier(c, kv.value); // Avoid processing this decl twice
+ const record_loc = ZigClangRecordDecl_getLocation(record_decl);
- const container_kind_name = if (ZigClangRecordDecl_isUnion(record_decl))
- "union"
- else if (ZigClangRecordDecl_isStruct(record_decl))
- "struct"
- else
- return emitWarning(c, ZigClangRecordDecl_getLocation(record_decl), "record {} is not a struct or union", .{bare_name});
+ var bare_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, record_decl)));
+ var is_unnamed = false;
+ if (ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl) or bare_name.len == 0) {
+ bare_name = try std.fmt.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()});
+ is_unnamed = true;
+ }
- if (ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl) or bare_name.len == 0)
- return;
+ var container_kind_name: []const u8 = undefined;
+ var container_kind: std.zig.Token.Id = undefined;
+ if (ZigClangRecordDecl_isUnion(record_decl)) {
+ container_kind_name = "union";
+ container_kind = .Keyword_union;
+ } else if (ZigClangRecordDecl_isStruct(record_decl)) {
+ container_kind_name = "struct";
+ container_kind = .Keyword_struct;
+ } else {
+ try emitWarning(c, record_loc, "record {} is not a struct or union", .{bare_name});
+ return null;
+ }
const name = try std.fmt.allocPrint(c.a(), "{}_{}", .{ container_kind_name, bare_name });
_ = try c.decl_table.put(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)), name);
@@ -588,16 +598,211 @@ fn resolveRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!
const node = try transCreateNodeVarDecl(c, true, true, name);
node.eq_token = try appendToken(c, .Equal, "=");
- node.init_node = transRecordDecl(c, record_decl) catch |err| switch (err) {
- error.UnsupportedType => {
- return failDecl(c, ZigClangRecordDecl_getLocation(record_decl), name, "unable to resolve record type", .{});
- },
- error.OutOfMemory => |e| return e,
+
+ var semicolon: ast.TokenIndex = undefined;
+ node.init_node = blk: {
+ const rp = makeRestorePoint(c);
+ const record_def = ZigClangRecordDecl_getDefinition(record_decl) orelse {
+ const opaque = try transCreateNodeOpaqueType(c);
+ semicolon = try appendToken(c, .Semicolon, ";");
+ break :blk opaque;
+ };
+
+ const extern_tok = try appendToken(c, .Keyword_extern, "extern");
+ const container_tok = try appendToken(c, container_kind, container_kind_name);
+ const lbrace_token = try appendToken(c, .LBrace, "{");
+
+ const container_node = try c.a().create(ast.Node.ContainerDecl);
+ container_node.* = .{
+ .layout_token = extern_tok,
+ .kind_token = container_tok,
+ .init_arg_expr = .None,
+ .fields_and_decls = ast.Node.ContainerDecl.DeclList.init(c.a()),
+ .lbrace_token = lbrace_token,
+ .rbrace_token = undefined,
+ };
+
+ var it = ZigClangRecordDecl_field_begin(record_def);
+ const end_it = ZigClangRecordDecl_field_end(record_def);
+ while (ZigClangRecordDecl_field_iterator_neq(it, end_it)) : (it = ZigClangRecordDecl_field_iterator_next(it)) {
+ const field_decl = ZigClangRecordDecl_field_iterator_deref(it);
+ const field_loc = ZigClangFieldDecl_getLocation(field_decl);
+
+ if (ZigClangFieldDecl_isBitField(field_decl)) {
+ const opaque = try transCreateNodeOpaqueType(c);
+ semicolon = try appendToken(c, .Semicolon, ";");
+ try emitWarning(c, field_loc, "{} demoted to opaque type - has bitfield", .{container_kind_name});
+ break :blk opaque;
+ }
+
+ const field_name = try appendIdentifier(c, try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, field_decl))));
+ _ = try appendToken(c, .Colon, ":");
+ const field_type = transQualType(rp, ZigClangFieldDecl_getType(field_decl), field_loc) catch |err| switch (err) {
+ error.UnsupportedType => {
+ try failDecl(c, record_loc, name, "unable to translate {} member type", .{container_kind_name});
+ return null;
+ },
+ else => |e| return e,
+ };
+
+ const field_node = try c.a().create(ast.Node.ContainerField);
+ field_node.* = .{
+ .doc_comments = null,
+ .comptime_token = null,
+ .name_token = field_name,
+ .type_expr = field_type,
+ .value_expr = null,
+ .align_expr = null,
+ };
+
+ try container_node.fields_and_decls.push(&field_node.base);
+ _ = try appendToken(c, .Comma, ",");
+ }
+ container_node.rbrace_token = try appendToken(c, .RBrace, "}");
+ semicolon = try appendToken(c, .Semicolon, ";");
+ break :blk &container_node.base;
};
+ node.semicolon_token = semicolon;
+
+ try addTopLevelDecl(c, name, &node.base);
+ if (!is_unnamed)
+ try c.alias_list.push(.{ .alias = bare_name, .name = name });
+ return transCreateNodeIdentifier(c, name);
+}
+
+fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.Node {
+ if (c.decl_table.get(@ptrToInt(ZigClangEnumDecl_getCanonicalDecl(enum_decl)))) |name|
+ return try transCreateNodeIdentifier(c, name.value); // Avoid processing this decl twice
+ const rp = makeRestorePoint(c);
+ const enum_loc = ZigClangEnumDecl_getLocation(enum_decl);
+
+ var bare_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, enum_decl)));
+ var is_unnamed = false;
+ if (bare_name.len == 0) {
+ bare_name = try std.fmt.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()});
+ is_unnamed = true;
+ }
+
+ const name = try std.fmt.allocPrint(c.a(), "enum_{}", .{bare_name});
+ _ = try c.decl_table.put(@ptrToInt(ZigClangEnumDecl_getCanonicalDecl(enum_decl)), name);
+ const node = try transCreateNodeVarDecl(c, true, true, name);
+ node.eq_token = try appendToken(c, .Equal, "=");
+
+ node.init_node = if (ZigClangEnumDecl_getDefinition(enum_decl)) |enum_def| blk: {
+ var pure_enum = true;
+ var it = ZigClangEnumDecl_enumerator_begin(enum_def);
+ var end_it = ZigClangEnumDecl_enumerator_end(enum_def);
+ while (ZigClangEnumDecl_enumerator_iterator_neq(it, end_it)) : (it = ZigClangEnumDecl_enumerator_iterator_next(it)) {
+ const enum_const = ZigClangEnumDecl_enumerator_iterator_deref(it);
+ if (ZigClangEnumConstantDecl_getInitExpr(enum_const)) |_| {
+ pure_enum = false;
+ break;
+ }
+ }
+
+ const extern_tok = try appendToken(c, .Keyword_extern, "extern");
+ const container_tok = try appendToken(c, .Keyword_enum, "enum");
+
+ const container_node = try c.a().create(ast.Node.ContainerDecl);
+ container_node.* = .{
+ .layout_token = extern_tok,
+ .kind_token = container_tok,
+ .init_arg_expr = .None,
+ .fields_and_decls = ast.Node.ContainerDecl.DeclList.init(c.a()),
+ .lbrace_token = undefined,
+ .rbrace_token = undefined,
+ };
+
+ const int_type = ZigClangEnumDecl_getIntegerType(enum_decl);
+
+ // TODO only emit this tag type if the enum tag type is not the default.
+ // I don't know what the default is, need to figure out how clang is deciding.
+ // it appears to at least be different across gcc/msvc
+ if (!isCBuiltinType(int_type, .UInt) and
+ !isCBuiltinType(int_type, .Int))
+ {
+ _ = try appendToken(c, .LParen, "(");
+ container_node.init_arg_expr = .{
+ .Type = transQualType(rp, int_type, enum_loc) catch |err| switch (err) {
+ error.UnsupportedType => {
+ try failDecl(c, enum_loc, name, "unable to translate enum tag type", .{});
+ return null;
+ },
+ else => |e| return e,
+ },
+ };
+ _ = try appendToken(c, .RParen, ")");
+ }
+
+ container_node.lbrace_token = try appendToken(c, .LBrace, "{");
+
+ it = ZigClangEnumDecl_enumerator_begin(enum_def);
+ end_it = ZigClangEnumDecl_enumerator_end(enum_def);
+ while (ZigClangEnumDecl_enumerator_iterator_neq(it, end_it)) : (it = ZigClangEnumDecl_enumerator_iterator_next(it)) {
+ const enum_const = ZigClangEnumDecl_enumerator_iterator_deref(it);
+
+ const enum_val_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, enum_const)));
+
+ const field_name = if (!is_unnamed and std.mem.startsWith(u8, enum_val_name, bare_name))
+ enum_val_name[bare_name.len..]
+ else
+ enum_val_name;
+
+ const field_name_tok = try appendIdentifier(c, field_name);
+
+ const int_node = if (!pure_enum) blk: {
+ _ = try appendToken(c, .Colon, "=");
+ break :blk try transCreateNodeAPInt(c, ZigClangEnumConstantDecl_getInitVal(enum_const));
+ } else
+ null;
+
+ const field_node = try c.a().create(ast.Node.ContainerField);
+ field_node.* = .{
+ .doc_comments = null,
+ .comptime_token = null,
+ .name_token = field_name_tok,
+ .type_expr = null,
+ .value_expr = int_node,
+ .align_expr = null,
+ };
+
+ try container_node.fields_and_decls.push(&field_node.base);
+ _ = try appendToken(c, .Comma, ",");
+ // In C each enum value is in the global namespace. So we put them there too.
+ // At this point we can rely on the enum emitting successfully.
+ try addEnumTopLevel(c, name, field_name, enum_val_name);
+ }
+ container_node.rbrace_token = try appendToken(c, .RBrace, "}");
+
+ break :blk &container_node.base;
+ } else
+ try transCreateNodeOpaqueType(c);
+
node.semicolon_token = try appendToken(c, .Semicolon, ";");
try addTopLevelDecl(c, name, &node.base);
- try c.alias_list.push(.{ .alias = bare_name, .name = name });
+ if (!is_unnamed)
+ try c.alias_list.push(.{ .alias = bare_name, .name = name });
+ return transCreateNodeIdentifier(c, name);
+}
+
+fn addEnumTopLevel(c: *Context, enum_name: []const u8, field_name: []const u8, enum_val_name: []const u8) !void {
+ const node = try transCreateNodeVarDecl(c, true, true, enum_val_name);
+ node.eq_token = try appendToken(c, .Equal, "=");
+ const enum_ident = try transCreateNodeIdentifier(c, enum_name);
+ const period_tok = try appendToken(c, .Period, ".");
+ const field_ident = try transCreateNodeIdentifier(c, field_name);
+ node.semicolon_token = try appendToken(c, .Semicolon, ";");
+
+ const field_access_node = try c.a().create(ast.Node.InfixOp);
+ field_access_node.* = .{
+ .op_token = period_tok,
+ .lhs = enum_ident,
+ .op = .Period,
+ .rhs = field_ident,
+ };
+ node.init_node = &field_access_node.base;
+ try addTopLevelDecl(c, field_name, &node.base);
}
fn createAlias(c: *Context, alias: var) !void {
@@ -1452,7 +1657,6 @@ fn transSwitch(
switch_scope.pending_block.rbrace = try appendToken(rp.c, .RBrace, "}");
return &switch_scope.pending_block.base;
}
-
fn transCase(
rp: RestorePoint,
@@ -1675,222 +1879,6 @@ fn transQualType(rp: RestorePoint, qt: ZigClangQualType, source_loc: ZigClangSou
return transType(rp, ZigClangQualType_getTypePtr(qt), source_loc);
}
-fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) TypeError!*ast.Node {
- const rp = makeRestorePoint(c);
-
- const record_loc = ZigClangRecordDecl_getLocation(record_decl);
-
- var container_kind_name: []const u8 = undefined;
- var container_kind: std.zig.Token.Id = undefined;
-
- if (ZigClangRecordDecl_isUnion(record_decl)) {
- container_kind_name = "union";
- container_kind = .Keyword_union;
- } else if (ZigClangRecordDecl_isStruct(record_decl)) {
- container_kind_name = "struct";
- container_kind = .Keyword_struct;
- } else {
- return revertAndWarn(
- rp,
- error.UnsupportedType,
- record_loc,
- "unsupported record type",
- .{},
- );
- }
-
- const record_def = ZigClangRecordDecl_getDefinition(record_decl) orelse {
- return transCreateNodeOpaqueType(c);
- };
-
- const extern_tok = try appendToken(c, .Keyword_extern, "extern");
- const container_tok = try appendToken(c, container_kind, container_kind_name);
- const lbrace_token = try appendToken(c, .LBrace, "{");
-
- const container_node = try c.a().create(ast.Node.ContainerDecl);
- container_node.* = .{
- .layout_token = extern_tok,
- .kind_token = container_tok,
- .init_arg_expr = .None,
- .fields_and_decls = ast.Node.ContainerDecl.DeclList.init(c.a()),
- .lbrace_token = lbrace_token,
- .rbrace_token = undefined,
- };
-
- var it = ZigClangRecordDecl_field_begin(record_def);
- const end_it = ZigClangRecordDecl_field_end(record_def);
- while (ZigClangRecordDecl_field_iterator_neq(it, end_it)) : (it = ZigClangRecordDecl_field_iterator_next(it)) {
- const field_decl = ZigClangRecordDecl_field_iterator_deref(it);
- const field_loc = ZigClangFieldDecl_getLocation(field_decl);
-
- if (ZigClangFieldDecl_isBitField(field_decl)) {
- rp.activate();
- const node = try transCreateNodeOpaqueType(c);
- try emitWarning(c, field_loc, "{} demoted to opaque type - has bitfield", .{container_kind_name});
- return node;
- }
-
- const field_name = try appendIdentifier(c, try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, field_decl))));
- _ = try appendToken(c, .Colon, ":");
- const field_type = try transQualType(rp, ZigClangFieldDecl_getType(field_decl), field_loc);
-
- const field_node = try c.a().create(ast.Node.ContainerField);
- field_node.* = .{
- .doc_comments = null,
- .comptime_token = null,
- .name_token = field_name,
- .type_expr = field_type,
- .value_expr = null,
- .align_expr = null,
- };
-
- try container_node.fields_and_decls.push(&field_node.base);
- _ = try appendToken(c, .Comma, ",");
- }
-
- container_node.rbrace_token = try appendToken(c, .RBrace, "}");
- return &container_node.base;
-}
-
-fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.Node {
- if (c.decl_table.get(@ptrToInt(ZigClangEnumDecl_getCanonicalDecl(enum_decl)))) |name|
- return try transCreateNodeIdentifier(c, name.value); // Avoid processing this decl twice
- const rp = makeRestorePoint(c);
- const enum_loc = ZigClangEnumDecl_getLocation(enum_decl);
-
- var bare_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, enum_decl)));
- var is_unnamed = false;
- if (bare_name.len == 0) {
- bare_name = try std.fmt.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()});
- is_unnamed = true;
- }
-
- const name = try std.fmt.allocPrint(c.a(), "enum_{}", .{bare_name});
- _ = try c.decl_table.put(@ptrToInt(ZigClangEnumDecl_getCanonicalDecl(enum_decl)), name);
- const node = try transCreateNodeVarDecl(c, true, true, name);
- node.eq_token = try appendToken(c, .Equal, "=");
-
- node.init_node = if (ZigClangEnumDecl_getDefinition(enum_decl)) |enum_def| blk: {
- var pure_enum = true;
- var it = ZigClangEnumDecl_enumerator_begin(enum_def);
- var end_it = ZigClangEnumDecl_enumerator_end(enum_def);
- while (ZigClangEnumDecl_enumerator_iterator_neq(it, end_it)) : (it = ZigClangEnumDecl_enumerator_iterator_next(it)) {
- const enum_const = ZigClangEnumDecl_enumerator_iterator_deref(it);
- if (ZigClangEnumConstantDecl_getInitExpr(enum_const)) |_| {
- pure_enum = false;
- break;
- }
- }
-
- const extern_tok = try appendToken(c, .Keyword_extern, "extern");
- const container_tok = try appendToken(c, .Keyword_enum, "enum");
-
- const container_node = try c.a().create(ast.Node.ContainerDecl);
- container_node.* = .{
- .layout_token = extern_tok,
- .kind_token = container_tok,
- .init_arg_expr = .None,
- .fields_and_decls = ast.Node.ContainerDecl.DeclList.init(c.a()),
- .lbrace_token = undefined,
- .rbrace_token = undefined,
- };
-
- const int_type = ZigClangEnumDecl_getIntegerType(enum_decl);
-
- // TODO only emit this tag type if the enum tag type is not the default.
- // I don't know what the default is, need to figure out how clang is deciding.
- // it appears to at least be different across gcc/msvc
- if (!isCBuiltinType(int_type, .UInt) and
- !isCBuiltinType(int_type, .Int))
- {
- _ = try appendToken(c, .LParen, "(");
- container_node.init_arg_expr = .{
- .Type = transQualType(rp, int_type, enum_loc) catch |err| switch (err) {
- error.UnsupportedType => {
- if (is_unnamed) {
- try emitWarning(c, enum_loc, "unable to translate enum tag type", .{});
- } else {
- try failDecl(c, enum_loc, name, "unable to translate enum tag type", .{});
- }
- return null;
- },
- else => |e| return e,
- },
- };
- _ = try appendToken(c, .RParen, ")");
- }
-
- container_node.lbrace_token = try appendToken(c, .LBrace, "{");
-
- it = ZigClangEnumDecl_enumerator_begin(enum_def);
- end_it = ZigClangEnumDecl_enumerator_end(enum_def);
- while (ZigClangEnumDecl_enumerator_iterator_neq(it, end_it)) : (it = ZigClangEnumDecl_enumerator_iterator_next(it)) {
- const enum_const = ZigClangEnumDecl_enumerator_iterator_deref(it);
-
- const enum_val_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, enum_const)));
-
- const field_name = if (!is_unnamed and std.mem.startsWith(u8, enum_val_name, bare_name))
- enum_val_name[bare_name.len..]
- else
- enum_val_name;
-
- const field_name_tok = try appendIdentifier(c, field_name);
-
- const int_node = if (!pure_enum) blk: {
- _ = try appendToken(c, .Colon, "=");
- break :blk try transCreateNodeAPInt(c, ZigClangEnumConstantDecl_getInitVal(enum_const));
- } else
- null;
-
- const field_node = try c.a().create(ast.Node.ContainerField);
- field_node.* = .{
- .doc_comments = null,
- .comptime_token = null,
- .name_token = field_name_tok,
- .type_expr = null,
- .value_expr = int_node,
- .align_expr = null,
- };
-
- try container_node.fields_and_decls.push(&field_node.base);
- _ = try appendToken(c, .Comma, ",");
- // In C each enum value is in the global namespace. So we put them there too.
- // At this point we can rely on the enum emitting successfully.
- try addEnumTopLevel(c, name, field_name, enum_val_name);
- }
- container_node.rbrace_token = try appendToken(c, .RBrace, "}");
-
- break :blk &container_node.base;
- } else
- try transCreateNodeOpaqueType(c);
-
- node.semicolon_token = try appendToken(c, .Semicolon, ";");
-
- try addTopLevelDecl(c, name, &node.base);
- if (!is_unnamed)
- try c.alias_list.push(.{ .alias = bare_name, .name = name });
- return transCreateNodeIdentifier(c, name);
-}
-
-fn addEnumTopLevel(c: *Context, enum_name: []const u8, field_name: []const u8, enum_val_name: []const u8) !void {
- const node = try transCreateNodeVarDecl(c, true, true, enum_val_name);
- node.eq_token = try appendToken(c, .Equal, "=");
- const enum_ident = try transCreateNodeIdentifier(c, enum_name);
- const period_tok = try appendToken(c, .Period, ".");
- const field_ident = try transCreateNodeIdentifier(c, field_name);
- node.semicolon_token = try appendToken(c, .Semicolon, ";");
-
- const field_access_node = try c.a().create(ast.Node.InfixOp);
- field_access_node.* = .{
- .op_token = period_tok,
- .lhs = enum_ident,
- .op = .Period,
- .rhs = field_ident,
- };
- node.init_node = &field_access_node.base;
- try addTopLevelDecl(c, field_name, &node.base);
-}
-
fn isCBuiltinType(qt: ZigClangQualType, kind: ZigClangBuiltinTypeKind) bool {
const c_type = qualTypeCanon(qt);
if (ZigClangType_getTypeClass(c_type) != .Builtin)
@@ -2591,7 +2579,7 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
else => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported builtin type", .{}),
});
},
- .FunctionProto => {
+ .FunctionProto, .FunctionNoProto => {
const fn_proto_ty = @ptrCast(*const ZigClangFunctionProtoType, ty);
const fn_proto = try transFnProto(rp, null, fn_proto_ty, source_loc, null, false);
return &fn_proto.base;
@@ -2666,24 +2654,15 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
const typedef_ty = @ptrCast(*const ZigClangTypedefType, ty);
const typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
- const typedef_name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, typedef_decl)));
- return transCreateNodeIdentifier(rp.c, typedef_name);
+ return (try transTypeDef(rp.c, typedef_decl)) orelse
+ revertAndWarn(rp, error.UnsupportedType, source_loc, "unable to translate typedef declaration", .{});
},
.Record => {
const record_ty = @ptrCast(*const ZigClangRecordType, ty);
- // TODO this sould get the name from decl_table
- // struct Foo {
- // struct Bar{
- // int b;
- // };
- // struct Bar c;
- // };
const record_decl = ZigClangRecordType_getDecl(record_ty);
- if (try getContainerName(rp, record_decl)) |name|
- return transCreateNodeIdentifier(rp.c, name)
- else
- return transRecordDecl(rp.c, record_decl);
+ return (try transRecordDecl(rp.c, record_decl)) orelse
+ revertAndWarn(rp, error.UnsupportedType, source_loc, "unable to resolve record declaration", .{});
},
.Enum => {
const enum_ty = @ptrCast(*const ZigClangEnumType, ty);
@@ -2704,6 +2683,10 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
const attributed_ty = @ptrCast(*const ZigClangAttributedType, ty);
return transQualType(rp, ZigClangAttributedType_getEquivalentType(attributed_ty), source_loc);
},
+ .MacroQualified => {
+ const macroqualified_ty = @ptrCast(*const ZigClangMacroQualifiedType, ty);
+ return transQualType(rp, ZigClangMacroQualifiedType_getModifiedType(macroqualified_ty), source_loc);
+ },
else => {
const type_name = rp.c.str(ZigClangType_getTypeClassName(ty));
return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported type: '{}'", .{type_name});
@@ -2711,22 +2694,6 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
}
}
-fn getContainerName(rp: RestorePoint, record_decl: *const ZigClangRecordDecl) !?[]const u8 {
- const bare_name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, record_decl)));
-
- const container_kind_name = if (ZigClangRecordDecl_isUnion(record_decl))
- "union"
- else if (ZigClangRecordDecl_isStruct(record_decl))
- "struct"
- else
- return revertAndWarn(rp, error.UnsupportedType, ZigClangRecordDecl_getLocation(record_decl), "record {} is not a struct or union", .{bare_name});
-
- if (ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl) or bare_name.len == 0)
- return null;
-
- return try std.fmt.allocPrint(rp.c.a(), "{}_{}", .{ container_kind_name, bare_name });
-}
-
fn isCVoid(qt: ZigClangQualType) bool {
const ty = ZigClangQualType_getTypePtr(qt);
if (ZigClangType_getTypeClass(ty) == .Builtin) {
@@ -2909,14 +2876,13 @@ fn finishTransFnProto(
};
const fn_proto = try rp.c.a().create(ast.Node.FnProto);
- fn_proto.* = ast.Node.FnProto{
- .base = ast.Node{ .id = ast.Node.Id.FnProto },
+ fn_proto.* = .{
.doc_comments = null,
.visib_token = pub_tok,
.fn_token = fn_tok,
.name_token = name_tok,
.params = fn_params,
- .return_type = ast.Node.FnProto.ReturnType{ .Explicit = return_type_node },
+ .return_type = .{ .Explicit = return_type_node },
.var_args_token = null, // TODO this field is broken in the AST data model
.extern_export_inline_token = extern_export_inline_tok,
.cc_token = cc_tok,
test/translate_c.zig
@@ -228,7 +228,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ struct Foo *foo;
\\};
, &[_][]const u8{
- \\pub const struct_Foo = @OpaqueType()
+ \\pub const struct_Foo = @OpaqueType();
,
\\pub const struct_Bar = extern struct {
\\ foo: ?*struct_Foo,
@@ -622,18 +622,15 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\#define glClearPFN PFNGLCLEARPROC
, &[_][]const u8{
\\pub const GLbitfield = c_uint;
- ,
\\pub const PFNGLCLEARPROC = ?extern fn (GLbitfield) void;
- ,
\\pub const OpenGLProc = ?extern fn () void;
- ,
+ \\pub const struct_unnamed_1 = extern struct {
+ \\ Clear: PFNGLCLEARPROC,
+ \\};
\\pub const union_OpenGLProcs = extern union {
\\ ptr: [1]OpenGLProc,
- \\ gl: extern struct {
- \\ Clear: PFNGLCLEARPROC,
- \\ },
+ \\ gl: struct_unnamed_1,
\\};
- ,
\\pub extern var glProcs: union_OpenGLProcs;
,
\\pub const glClearPFN = PFNGLCLEARPROC;
@@ -891,6 +888,22 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\}
});
+ cases.add_2("type referenced struct",
+ \\struct Foo {
+ \\ struct Bar{
+ \\ int b;
+ \\ };
+ \\ struct Bar c;
+ \\};
+ , &[_][]const u8{
+ \\pub const struct_Bar = extern struct {
+ \\ b: c_int,
+ \\};
+ \\pub const struct_Foo = extern struct {
+ \\ c: struct_Bar,
+ \\};
+ });
+
/////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
if (builtin.os != builtin.Os.windows) {