authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-14 01:43:55+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-14 02:00:01+02:00
loge4ca1f441bf0c54e3fd447a2db6567a936175002
tree95f8c7f8845580b797a6f4dded0cac0c64f70fd4
parent21a85d4fb643cf14cf4afbcfc7ecfd359b910097
signature Commit is signed but in an unrecognized format.

translate-c-2 record type


4 files changed, 304 insertions(+), 24 deletions(-)

lib/std/zig/render.zig+2-2
...@@ -193,6 +193,7 @@ fn renderRoot(...@@ -193,6 +193,7 @@ fn renderRoot(
193fn renderExtraNewline(tree: *ast.Tree, stream: var, start_col: *usize, node: *ast.Node) @TypeOf(stream).Child.Error!void {193fn renderExtraNewline(tree: *ast.Tree, stream: var, start_col: *usize, node: *ast.Node) @TypeOf(stream).Child.Error!void {
194 const first_token = node.firstToken();194 const first_token = node.firstToken();
195 var prev_token = first_token;195 var prev_token = first_token;
196 if (prev_token == 0) return;
196 while (tree.tokens.at(prev_token - 1).id == .DocComment) {197 while (tree.tokens.at(prev_token - 1).id == .DocComment) {
197 prev_token -= 1;198 prev_token -= 1;
198 }199 }
...@@ -2174,8 +2175,7 @@ fn renderTokenOffset(...@@ -2174,8 +2175,7 @@ fn renderTokenOffset(
2174 }2175 }
21752176
2176 while (true) {2177 while (true) {
2177 assert(loc.line != 0);2178 const newline_count = if (loc.line < 2) @as(u8, 1) else @as(u8, 2);
2178 const newline_count = if (loc.line == 1) @as(u8, 1) else @as(u8, 2);
2179 try stream.writeByteNTimes('\n', newline_count);2179 try stream.writeByteNTimes('\n', newline_count);
2180 try stream.writeByteNTimes(' ', indent);2180 try stream.writeByteNTimes(' ', indent);
2181 try stream.write(mem.trimRight(u8, tree.tokenSlicePtr(next_token), " "));2181 try stream.write(mem.trimRight(u8, tree.tokenSlicePtr(next_token), " "));
src-self-hosted/clang.zig+25-1
...@@ -709,6 +709,20 @@ pub const ZigClangStringLiteral_StringKind = extern enum {...@@ -709,6 +709,20 @@ pub const ZigClangStringLiteral_StringKind = extern enum {
709 UTF32,709 UTF32,
710};710};
711711
712pub const ZigClangRecordDecl_field_iterator = extern struct {
713 opaque: *c_void,
714};
715
716pub const ZigClangElaboratedTypeKeyword = extern enum {
717 Struct,
718 Interface,
719 Union,
720 Class,
721 Enum,
722 Typename,
723 None,
724};
725
712pub extern fn ZigClangSourceManager_getSpellingLoc(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) struct_ZigClangSourceLocation;726pub extern fn ZigClangSourceManager_getSpellingLoc(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) struct_ZigClangSourceLocation;
713pub extern fn ZigClangSourceManager_getFilename(self: *const struct_ZigClangSourceManager, SpellingLoc: struct_ZigClangSourceLocation) ?[*:0]const u8;727pub extern fn ZigClangSourceManager_getFilename(self: *const struct_ZigClangSourceManager, SpellingLoc: struct_ZigClangSourceLocation) ?[*:0]const u8;
714pub extern fn ZigClangSourceManager_getSpellingLineNumber(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint;728pub extern fn ZigClangSourceManager_getSpellingLineNumber(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint;
...@@ -718,7 +732,7 @@ pub extern fn ZigClangASTContext_getPointerType(self: ?*const struct_ZigClangAST...@@ -718,7 +732,7 @@ pub extern fn ZigClangASTContext_getPointerType(self: ?*const struct_ZigClangAST
718pub extern fn ZigClangASTUnit_getASTContext(self: ?*struct_ZigClangASTUnit) ?*struct_ZigClangASTContext;732pub extern fn ZigClangASTUnit_getASTContext(self: ?*struct_ZigClangASTUnit) ?*struct_ZigClangASTContext;
719pub extern fn ZigClangASTUnit_getSourceManager(self: *struct_ZigClangASTUnit) *struct_ZigClangSourceManager;733pub extern fn ZigClangASTUnit_getSourceManager(self: *struct_ZigClangASTUnit) *struct_ZigClangSourceManager;
720pub extern fn ZigClangASTUnit_visitLocalTopLevelDecls(self: *struct_ZigClangASTUnit, context: ?*c_void, Fn: ?extern fn (?*c_void, *const struct_ZigClangDecl) bool) bool;734pub extern fn ZigClangASTUnit_visitLocalTopLevelDecls(self: *struct_ZigClangASTUnit, context: ?*c_void, Fn: ?extern fn (?*c_void, *const struct_ZigClangDecl) bool) bool;
721pub extern fn ZigClangRecordType_getDecl(record_ty: ?*const struct_ZigClangRecordType) ?*const struct_ZigClangRecordDecl;735pub extern fn ZigClangRecordType_getDecl(record_ty: ?*const struct_ZigClangRecordType) *const struct_ZigClangRecordDecl;
722pub extern fn ZigClangEnumType_getDecl(record_ty: ?*const struct_ZigClangEnumType) ?*const struct_ZigClangEnumDecl;736pub extern fn ZigClangEnumType_getDecl(record_ty: ?*const struct_ZigClangEnumType) ?*const struct_ZigClangEnumDecl;
723pub extern fn ZigClangRecordDecl_getCanonicalDecl(record_decl: ?*const struct_ZigClangRecordDecl) ?*const struct_ZigClangTagDecl;737pub extern fn ZigClangRecordDecl_getCanonicalDecl(record_decl: ?*const struct_ZigClangRecordDecl) ?*const struct_ZigClangTagDecl;
724pub extern fn ZigClangEnumDecl_getCanonicalDecl(self: ?*const struct_ZigClangEnumDecl) ?*const struct_ZigClangTagDecl;738pub extern fn ZigClangEnumDecl_getCanonicalDecl(self: ?*const struct_ZigClangEnumDecl) ?*const struct_ZigClangTagDecl;
...@@ -732,6 +746,11 @@ pub extern fn ZigClangDecl_getLocation(self: *const ZigClangDecl) ZigClangSource...@@ -732,6 +746,11 @@ pub extern fn ZigClangDecl_getLocation(self: *const ZigClangDecl) ZigClangSource
732pub extern fn ZigClangRecordDecl_isUnion(record_decl: ?*const struct_ZigClangRecordDecl) bool;746pub extern fn ZigClangRecordDecl_isUnion(record_decl: ?*const struct_ZigClangRecordDecl) bool;
733pub extern fn ZigClangRecordDecl_isStruct(record_decl: ?*const struct_ZigClangRecordDecl) bool;747pub extern fn ZigClangRecordDecl_isStruct(record_decl: ?*const struct_ZigClangRecordDecl) bool;
734pub extern fn ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl: ?*const struct_ZigClangRecordDecl) bool;748pub extern fn ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl: ?*const struct_ZigClangRecordDecl) bool;
749pub extern fn ZigClangRecordDecl_field_begin(*const struct_ZigClangRecordDecl) ZigClangRecordDecl_field_iterator;
750pub extern fn ZigClangRecordDecl_field_end(*const struct_ZigClangRecordDecl) ZigClangRecordDecl_field_iterator;
751pub extern fn ZigClangRecordDecl_field_iterator_next(ZigClangRecordDecl_field_iterator) ZigClangRecordDecl_field_iterator;
752pub extern fn ZigClangRecordDecl_field_iterator_deref(ZigClangRecordDecl_field_iterator) *const struct_ZigClangFieldDecl;
753pub extern fn ZigClangRecordDecl_field_iterator_neq(ZigClangRecordDecl_field_iterator, ZigClangRecordDecl_field_iterator) bool;
735pub extern fn ZigClangEnumDecl_getIntegerType(self: ?*const struct_ZigClangEnumDecl) struct_ZigClangQualType;754pub extern fn ZigClangEnumDecl_getIntegerType(self: ?*const struct_ZigClangEnumDecl) struct_ZigClangQualType;
736pub extern fn ZigClangDecl_getName_bytes_begin(decl: ?*const struct_ZigClangDecl) [*c]const u8;755pub extern fn ZigClangDecl_getName_bytes_begin(decl: ?*const struct_ZigClangDecl) [*c]const u8;
737pub extern fn ZigClangSourceLocation_eq(a: struct_ZigClangSourceLocation, b: struct_ZigClangSourceLocation) bool;756pub extern fn ZigClangSourceLocation_eq(a: struct_ZigClangSourceLocation, b: struct_ZigClangSourceLocation) bool;
...@@ -948,6 +967,7 @@ pub extern fn ZigClangDeclRefExpr_getDecl(*const ZigClangDeclRefExpr) *const Zig...@@ -948,6 +967,7 @@ pub extern fn ZigClangDeclRefExpr_getDecl(*const ZigClangDeclRefExpr) *const Zig
948967
949pub extern fn ZigClangParenType_getInnerType(*const ZigClangParenType) ZigClangQualType;968pub extern fn ZigClangParenType_getInnerType(*const ZigClangParenType) ZigClangQualType;
950969
970pub extern fn ZigClangElaboratedType_getKeyword(*const struct_ZigClangElaboratedType) ZigClangElaboratedTypeKeyword;
951pub extern fn ZigClangElaboratedType_getNamedType(*const ZigClangElaboratedType) ZigClangQualType;971pub extern fn ZigClangElaboratedType_getNamedType(*const ZigClangElaboratedType) ZigClangQualType;
952972
953pub extern fn ZigClangAttributedType_getEquivalentType(*const ZigClangAttributedType) ZigClangQualType;973pub extern fn ZigClangAttributedType_getEquivalentType(*const ZigClangAttributedType) ZigClangQualType;
...@@ -987,3 +1007,7 @@ pub extern fn ZigClangStringLiteral_getKind(*const ZigClangStringLiteral) ZigCla...@@ -987,3 +1007,7 @@ pub extern fn ZigClangStringLiteral_getKind(*const ZigClangStringLiteral) ZigCla
987pub extern fn ZigClangStringLiteral_getString_bytes_begin_size(*const ZigClangStringLiteral, *usize) [*c]const u8;1007pub extern fn ZigClangStringLiteral_getString_bytes_begin_size(*const ZigClangStringLiteral, *usize) [*c]const u8;
9881008
989pub extern fn ZigClangParenExpr_getSubExpr(*const ZigClangParenExpr) *const ZigClangExpr;1009pub extern fn ZigClangParenExpr_getSubExpr(*const ZigClangParenExpr) *const ZigClangExpr;
1010
1011pub extern fn ZigClangFieldDecl_isBitField(*const struct_ZigClangFieldDecl) bool;
1012pub extern fn ZigClangFieldDecl_getType(*const struct_ZigClangFieldDecl) struct_ZigClangQualType;
1013pub extern fn ZigClangFieldDecl_getLocation(*const struct_ZigClangFieldDecl) struct_ZigClangSourceLocation;
src-self-hosted/translate_c.zig+210-20
...@@ -15,7 +15,7 @@ pub const Error = error{OutOfMemory};...@@ -15,7 +15,7 @@ pub const Error = error{OutOfMemory};
15const TypeError = Error || error{UnsupportedType};15const TypeError = Error || error{UnsupportedType};
16const TransError = TypeError || error{UnsupportedTranslation};16const TransError = TypeError || error{UnsupportedTranslation};
1717
18const DeclTable = std.HashMap(usize, void, addrHash, addrEql);18const DeclTable = std.HashMap(usize, []const u8, addrHash, addrEql);
1919
20fn addrHash(x: usize) u32 {20fn addrHash(x: usize) u32 {
21 switch (@typeInfo(usize).Int.bits) {21 switch (@typeInfo(usize).Int.bits) {
...@@ -194,6 +194,7 @@ pub fn translate(...@@ -194,6 +194,7 @@ pub fn translate(
194194
195 tree.root_node.eof_token = try appendToken(&context, .Eof, "");195 tree.root_node.eof_token = try appendToken(&context, .Eof, "");
196 tree.source = source_buffer.toOwnedSlice();196 tree.source = source_buffer.toOwnedSlice();
197
197 if (false) {198 if (false) {
198 std.debug.warn("debug source:\n{}\n==EOF==\ntokens:\n", tree.source);199 std.debug.warn("debug source:\n{}\n==EOF==\ntokens:\n", tree.source);
199 var i: usize = 0;200 var i: usize = 0;
...@@ -220,13 +221,13 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void {...@@ -220,13 +221,13 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void {
220 return visitFnDecl(c, @ptrCast(*const ZigClangFunctionDecl, decl));221 return visitFnDecl(c, @ptrCast(*const ZigClangFunctionDecl, decl));
221 },222 },
222 .Typedef => {223 .Typedef => {
223 try resolveTypeDef(c, @ptrCast(*const ZigClangTypedefNameDecl, decl));224 return resolveTypeDef(c, @ptrCast(*const ZigClangTypedefNameDecl, decl));
224 },225 },
225 .Enum => {226 .Enum => {
226 try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for enums", .{});227 try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for enums", .{});
227 },228 },
228 .Record => {229 .Record => {
229 try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for structs", .{});230 return resolveRecordDecl(c, @ptrCast(*const ZigClangRecordDecl, decl));
230 },231 },
231 .Var => {232 .Var => {
232 return visitVarDecl(c, @ptrCast(*const ZigClangVarDecl, decl));233 return visitVarDecl(c, @ptrCast(*const ZigClangVarDecl, decl));
...@@ -239,9 +240,10 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void {...@@ -239,9 +240,10 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void {
239}240}
240241
241fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {242fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
242 if (try c.decl_table.put(@ptrToInt(fn_decl), {})) |_| return; // Avoid processing this decl twice243 if (c.decl_table.contains(@ptrToInt(fn_decl))) return; // Avoid processing this decl twice
243 const rp = makeRestorePoint(c);244 const rp = makeRestorePoint(c);
244 const fn_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, fn_decl)));245 const fn_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, fn_decl)));
246 _ = try c.decl_table.put(@ptrToInt(fn_decl), fn_name);
245 const fn_decl_loc = ZigClangFunctionDecl_getLocation(fn_decl);247 const fn_decl_loc = ZigClangFunctionDecl_getLocation(fn_decl);
246 const fn_qt = ZigClangFunctionDecl_getType(fn_decl);248 const fn_qt = ZigClangFunctionDecl_getType(fn_decl);
247 const fn_type = ZigClangQualType_getTypePtr(fn_qt);249 const fn_type = ZigClangQualType_getTypePtr(fn_qt);
...@@ -303,7 +305,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {...@@ -303,7 +305,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
303}305}
304306
305fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {307fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
306 if (try c.decl_table.put(@ptrToInt(var_decl), {})) |_| return; // Avoid processing this decl twice308 if (c.decl_table.contains(@ptrToInt(var_decl))) return; // Avoid processing this decl twice
307 const rp = makeRestorePoint(c);309 const rp = makeRestorePoint(c);
308 const visib_tok = try appendToken(c, .Keyword_pub, "pub");310 const visib_tok = try appendToken(c, .Keyword_pub, "pub");
309311
...@@ -314,6 +316,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {...@@ -314,6 +316,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
314316
315 var scope = &c.global_scope.base;317 var scope = &c.global_scope.base;
316 const var_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, var_decl)));318 const var_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, var_decl)));
319 _ = try c.decl_table.put(@ptrToInt(var_decl), var_name);
317 const var_decl_loc = ZigClangVarDecl_getLocation(var_decl);320 const var_decl_loc = ZigClangVarDecl_getLocation(var_decl);
318321
319 const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl);322 const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl);
...@@ -385,12 +388,13 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {...@@ -385,12 +388,13 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
385}388}
386389
387fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Error!void {390fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Error!void {
388 if (try c.decl_table.put(@ptrToInt(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl)), {})) |_| return; // Avoid processing this decl twice391 if (c.decl_table.contains(@ptrToInt(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl)))) return; // Avoid processing this decl twice
389 const rp = makeRestorePoint(c);392 const rp = makeRestorePoint(c);
390 const visib_tok = try appendToken(c, .Keyword_pub, "pub");393 const visib_tok = try appendToken(c, .Keyword_pub, "pub");
391 const const_tok = try appendToken(c, .Keyword_const, "const");394 const const_tok = try appendToken(c, .Keyword_const, "const");
392395
393 const typedef_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, typedef_decl)));396 const typedef_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, typedef_decl)));
397 _ = try c.decl_table.put(@ptrToInt(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl)), typedef_name);
394 const name_tok = try appendToken(c, .Identifier, typedef_name);398 const name_tok = try appendToken(c, .Identifier, typedef_name);
395 const eq_tok = try appendToken(c, .Equal, "=");399 const eq_tok = try appendToken(c, .Equal, "=");
396400
...@@ -398,9 +402,7 @@ fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Err...@@ -398,9 +402,7 @@ fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Err
398 const typedef_loc = ZigClangTypedefNameDecl_getLocation(typedef_decl);402 const typedef_loc = ZigClangTypedefNameDecl_getLocation(typedef_decl);
399 const type_node = transQualType(rp, child_qt, typedef_loc) catch |err| switch (err) {403 const type_node = transQualType(rp, child_qt, typedef_loc) catch |err| switch (err) {
400 error.UnsupportedType => {404 error.UnsupportedType => {
401 const node = try failDecl(c, typedef_loc, typedef_name, "unable to resolve typedef child type", .{});405 return failDecl(c, typedef_loc, typedef_name, "unable to resolve typedef child type", .{});
402 _ = try c.decl_table.put(@ptrToInt(typedef_decl), node);
403 return node;
404 },406 },
405 error.OutOfMemory => |e| return e,407 error.OutOfMemory => |e| return e,
406 };408 };
...@@ -426,6 +428,60 @@ fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Err...@@ -426,6 +428,60 @@ fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Err
426 try addTopLevelDecl(c, typedef_name, &node.base);428 try addTopLevelDecl(c, typedef_name, &node.base);
427}429}
428430
431fn resolveRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!void {
432 if (c.decl_table.contains(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)))) return; // Avoid processing this decl twice
433 const rp = makeRestorePoint(c);
434
435 const visib_tok = try appendToken(c, .Keyword_pub, "pub");
436 const const_tok = try appendToken(c, .Keyword_const, "const");
437
438 const bare_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, record_decl)));
439
440 const container_kind_name = if (ZigClangRecordDecl_isUnion(record_decl))
441 "union"
442 else if (ZigClangRecordDecl_isStruct(record_decl))
443 "struct"
444 else
445 return failDecl(c, ZigClangRecordDecl_getLocation(record_decl), bare_name, "record {} is not a struct or union", .{bare_name});
446
447 if (ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl) or bare_name.len == 0)
448 return;
449
450 const name = try std.fmt.allocPrint(c.a(), "{}_{}", .{ container_kind_name, bare_name });
451 _ = try c.decl_table.put(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)), name);
452 const name_tok = try appendToken(c, .Identifier, name);
453
454 const eq_tok = try appendToken(c, .Equal, "=");
455 const init_node = transRecordDecl(c, record_decl) catch |err| switch (err) {
456 error.UnsupportedType => {
457 return failDecl(c, ZigClangRecordDecl_getLocation(record_decl), name, "unable to resolve record type", .{});
458 },
459 error.OutOfMemory => |e| return e,
460 };
461 const semicolon_token = try appendToken(c, .Semicolon, ";");
462
463 const node = try c.a().create(ast.Node.VarDecl);
464 node.* = ast.Node.VarDecl{
465 .base = ast.Node{ .id = .VarDecl },
466 .doc_comments = null,
467 .visib_token = visib_tok,
468 .thread_local_token = null,
469 .name_token = name_tok,
470 .eq_token = eq_tok,
471 .mut_token = const_tok,
472 .comptime_token = null,
473 .extern_export_token = null,
474 .lib_name = null,
475 .type_node = null,
476 .align_node = null,
477 .section_node = null,
478 .init_node = init_node,
479 .semicolon_token = semicolon_token,
480 };
481
482 try addTopLevelDecl(c, name, &node.base);
483}
484
429const ResultUsed = enum {485const ResultUsed = enum {
430 used,486 used,
431 unused,487 unused,
...@@ -1148,22 +1204,113 @@ fn transQualType(rp: RestorePoint, qt: ZigClangQualType, source_loc: ZigClangSou...@@ -1148,22 +1204,113 @@ fn transQualType(rp: RestorePoint, qt: ZigClangQualType, source_loc: ZigClangSou
1148 return transType(rp, ZigClangQualType_getTypePtr(qt), source_loc);1204 return transType(rp, ZigClangQualType_getTypePtr(qt), source_loc);
1149}1205}
11501206
1207fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) TypeError!*ast.Node {
1208 const rp = makeRestorePoint(c);
1209
1210 const record_loc = ZigClangRecordDecl_getLocation(record_decl);
1211
1212 var container_kind_name: []const u8 = undefined;
1213 var container_kind: std.zig.Token.Id = undefined;
1214
1215 if (ZigClangRecordDecl_isUnion(record_decl)) {
1216 container_kind_name = "union";
1217 container_kind = .Keyword_union;
1218 } else if (ZigClangRecordDecl_isStruct(record_decl)) {
1219 container_kind_name = "struct";
1220 container_kind = .Keyword_struct;
1221 } else {
1222 return revertAndWarn(
1223 rp,
1224 error.UnsupportedType,
1225 record_loc,
1226 "unsupported record type",
1227 .{},
1228 );
1229 }
1230
1231 const record_def = ZigClangRecordDecl_getDefinition(record_decl) orelse {
1232 return transCreateNodeOpaqueType(c);
1233 };
1234
1235 const extern_tok = try appendToken(c, .Keyword_extern, "extern");
1236 const container_tok = try appendToken(c, container_kind, container_kind_name);
1237 const lbrace_token = try appendToken(c, .LBrace, "{");
1238
1239 const container_node = try c.a().create(ast.Node.ContainerDecl);
1240 container_node.* = .{
1241 .base = ast.Node{ .id = .ContainerDecl },
1242 .layout_token = extern_tok,
1243 .kind_token = container_tok,
1244 .init_arg_expr = .None,
1245 .fields_and_decls = ast.Node.ContainerDecl.DeclList.init(c.a()),
1246 .lbrace_token = lbrace_token,
1247 .rbrace_token = undefined, // TODO
1248 };
1249
1250 var it = ZigClangRecordDecl_field_begin(record_def);
1251 const end_it = ZigClangRecordDecl_field_end(record_def);
1252 while (ZigClangRecordDecl_field_iterator_neq(it, end_it)) : (it = ZigClangRecordDecl_field_iterator_next(it)) {
1253 const field_decl = ZigClangRecordDecl_field_iterator_deref(it);
1254 const field_loc = ZigClangFieldDecl_getLocation(field_decl);
1255
1256 if (ZigClangFieldDecl_isBitField(field_decl)) {
1257 rp.activate();
1258 const node = try transCreateNodeOpaqueType(c);
1259 try emitWarning(c, field_loc, "{} demoted to opaque type - has bitfield", .{container_kind_name});
1260 return node;
1261 }
1262
1263 const field_name = try appendToken(c, .Identifier, try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, field_decl))));
1264 _ = try appendToken(c, .Colon, ":");
1265 const field_type = try transQualType(rp, ZigClangFieldDecl_getType(field_decl), field_loc);
1266
1267 const field_node = try c.a().create(ast.Node.ContainerField);
1268 field_node.* = .{
1269 .doc_comments = null,
1270 .comptime_token = null,
1271 .name_token = field_name,
1272 .type_expr = field_type,
1273 .value_expr = null,
1274 .align_expr = null,
1275 };
1276
1277 try container_node.fields_and_decls.push(&field_node.base);
1278 _ = try appendToken(c, .Comma, ",");
1279 }
1280
1281 container_node.rbrace_token = try appendToken(c, .RBrace, "}");
1282 return &container_node.base;
1283}
1284
1151fn qualTypeIsPtr(qt: ZigClangQualType) bool {1285fn qualTypeIsPtr(qt: ZigClangQualType) bool {
1152 return ZigClangType_getTypeClass(qualTypeCanon(qt)) == .Pointer;1286 return ZigClangType_getTypeClass(qualTypeCanon(qt)) == .Pointer;
1153}1287}
11541288
1155fn qualTypeChildIsFnProto(qt: ZigClangQualType) bool {1289fn qualTypeChildIsFnProto(qt: ZigClangQualType) bool {
1156 const ty = ZigClangQualType_getTypePtr(qt);1290 const ty = ZigClangQualType_getTypePtr(qt);
1157 if (ZigClangType_getTypeClass(ty) == .Paren) {1291
1158 const paren_type = @ptrCast(*const ZigClangParenType, ty);1292 switch (ZigClangType_getTypeClass(ty)) {
1159 const inner_type = ZigClangParenType_getInnerType(paren_type);1293 .FunctionProto, .FunctionNoProto => return true,
1160 return ZigClangQualType_getTypeClass(inner_type) == .FunctionProto;1294 .Elaborated => {
1161 }1295 const elaborated_ty = @ptrCast(*const ZigClangElaboratedType, ty);
1162 if (ZigClangType_getTypeClass(ty) == .Attributed) {1296 return qualTypeChildIsFnProto(ZigClangElaboratedType_getNamedType(elaborated_ty));
1163 const attr_type = @ptrCast(*const ZigClangAttributedType, ty);1297 },
1164 return qualTypeChildIsFnProto(ZigClangAttributedType_getEquivalentType(attr_type));1298 .Typedef => {
1299 const typedef_ty = @ptrCast(*const ZigClangTypedefType, ty);
1300 const typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
1301 return qualTypeChildIsFnProto(ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl));
1302 },
1303 .Paren => {
1304 const paren_type = @ptrCast(*const ZigClangParenType, ty);
1305 const inner_type = ZigClangParenType_getInnerType(paren_type);
1306 return ZigClangQualType_getTypeClass(inner_type) == .FunctionProto;
1307 },
1308 .Attributed => {
1309 const attr_type = @ptrCast(*const ZigClangAttributedType, ty);
1310 return qualTypeChildIsFnProto(ZigClangAttributedType_getEquivalentType(attr_type));
1311 },
1312 else => return false,
1165 }1313 }
1166 return false;
1167}1314}
11681315
1169fn qualTypeCanon(qt: ZigClangQualType) *const ZigClangType {1316fn qualTypeCanon(qt: ZigClangQualType) *const ZigClangType {
...@@ -1197,7 +1344,18 @@ fn typeIsOpaque(c: *Context, ty: *const ZigClangType, loc: ZigClangSourceLocatio...@@ -1197,7 +1344,18 @@ fn typeIsOpaque(c: *Context, ty: *const ZigClangType, loc: ZigClangSourceLocatio
1197 .Record => {1344 .Record => {
1198 const record_ty = @ptrCast(*const ZigClangRecordType, ty);1345 const record_ty = @ptrCast(*const ZigClangRecordType, ty);
1199 const record_decl = ZigClangRecordType_getDecl(record_ty);1346 const record_decl = ZigClangRecordType_getDecl(record_ty);
1200 return (ZigClangRecordDecl_getDefinition(record_decl) == null);1347 const record_def = ZigClangRecordDecl_getDefinition(record_decl) orelse
1348 return true;
1349 var it = ZigClangRecordDecl_field_begin(record_def);
1350 const end_it = ZigClangRecordDecl_field_end(record_def);
1351 while (ZigClangRecordDecl_field_iterator_neq(it, end_it)) : (it = ZigClangRecordDecl_field_iterator_next(it)) {
1352 const field_decl = ZigClangRecordDecl_field_iterator_deref(it);
1353
1354 if (ZigClangFieldDecl_isBitField(field_decl)) {
1355 return true;
1356 }
1357 }
1358 return false;
1201 },1359 },
1202 .Elaborated => {1360 .Elaborated => {
1203 const elaborated_ty = @ptrCast(*const ZigClangElaboratedType, ty);1361 const elaborated_ty = @ptrCast(*const ZigClangElaboratedType, ty);
...@@ -1450,7 +1608,7 @@ fn transCreateNodeArrayInitializer(c: *Context, type_node: *ast.Node) !*ast.Node...@@ -1450,7 +1608,7 @@ fn transCreateNodeArrayInitializer(c: *Context, type_node: *ast.Node) !*ast.Node
1450}1608}
14511609
1452fn transCreateNodeInt(c: *Context, int: var) !*ast.Node {1610fn transCreateNodeInt(c: *Context, int: var) !*ast.Node {
1453 const token = try appendToken(c, .IntegerLiteral, try std.fmt.allocPrint(c.a(), "{}", .{int}));1611 const token = try appendTokenFmt(c, .IntegerLiteral, "{}", .{int});
1454 const node = try c.a().create(ast.Node.IntegerLiteral);1612 const node = try c.a().create(ast.Node.IntegerLiteral);
1455 node.* = ast.Node.IntegerLiteral{1613 node.* = ast.Node.IntegerLiteral{
1456 .base = ast.Node{ .id = .IntegerLiteral },1614 .base = ast.Node{ .id = .IntegerLiteral },
...@@ -1459,6 +1617,21 @@ fn transCreateNodeInt(c: *Context, int: var) !*ast.Node {...@@ -1459,6 +1617,21 @@ fn transCreateNodeInt(c: *Context, int: var) !*ast.Node {
1459 return &node.base;1617 return &node.base;
1460}1618}
14611619
1620fn transCreateNodeOpaqueType(c: *Context) !*ast.Node {
1621 const builtin_tok = try appendToken(c, .Builtin, "@OpaqueType");
1622 _ = try appendToken(c, .LParen, "(");
1623 const rparen_tok = try appendToken(c, .RParen, ")");
1624
1625 const call_node = try c.a().create(ast.Node.BuiltinCall);
1626 call_node.* = ast.Node.BuiltinCall{
1627 .base = ast.Node{ .id = ast.Node.Id.BuiltinCall },
1628 .builtin_token = builtin_tok,
1629 .params = ast.Node.BuiltinCall.ParamList.init(c.a()),
1630 .rparen_token = rparen_tok,
1631 };
1632 return &call_node.base;
1633}
1634
1462const RestorePoint = struct {1635const RestorePoint = struct {
1463 c: *Context,1636 c: *Context,
1464 token_index: ast.TokenIndex,1637 token_index: ast.TokenIndex,
...@@ -1580,9 +1753,26 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour...@@ -1580,9 +1753,26 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
1580 const typedef_ty = @ptrCast(*const ZigClangTypedefType, ty);1753 const typedef_ty = @ptrCast(*const ZigClangTypedefType, ty);
15811754
1582 const typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);1755 const typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
1756 // const typedef_name = rp.c.decl_table.get(@ptrToInt(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl))).?.value;
1583 const typedef_name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, typedef_decl)));1757 const typedef_name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, typedef_decl)));
1584 return appendIdentifier(rp.c, typedef_name);1758 return appendIdentifier(rp.c, typedef_name);
1585 },1759 },
1760 .Record => {
1761 const record_ty = @ptrCast(*const ZigClangRecordType, ty);
1762
1763 const record_decl = ZigClangRecordType_getDecl(record_ty);
1764 if (rp.c.decl_table.get(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)))) |kv|
1765 return appendIdentifier(rp.c, kv.value)
1766 else
1767 return transRecordDecl(rp.c, record_decl);
1768 },
1769 .Elaborated => {
1770 const elaborated_ty = @ptrCast(*const ZigClangElaboratedType, ty);
1771 switch (ZigClangElaboratedType_getKeyword(elaborated_ty)) {
1772 .Struct, .Enum, .Union => return try transQualType(rp, ZigClangElaboratedType_getNamedType(elaborated_ty), source_loc),
1773 else => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported elaborated type", .{}),
1774 }
1775 },
1586 else => {1776 else => {
1587 const type_name = rp.c.str(ZigClangType_getTypeClassName(ty));1777 const type_name = rp.c.str(ZigClangType_getTypeClassName(ty));
1588 return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported type: '{}'", .{type_name});1778 return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported type: '{}'", .{type_name});
test/translate_c.zig+67-1
...@@ -186,9 +186,75 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -186,9 +186,75 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
186 \\pub export var arr2: [*c]u8 = "hello";186 \\pub export var arr2: [*c]u8 = "hello";
187 });187 });
188188
189 cases.add_2("pointer to struct demoted to opaque due to bit fields",
190 \\struct Foo {
191 \\ unsigned int: 1;
192 \\};
193 \\struct Bar {
194 \\ struct Foo *foo;
195 \\};
196 , &[_][]const u8{ // TODO that semicolon is hideous
197 \\pub const struct_Foo = @OpaqueType() // /home/vexu/Documents/zig/zig/zig-cache/source.h:2:5: warning: struct demoted to opaque type - has bitfield
198 \\ ;
199 \\pub const struct_Bar = extern struct {
200 \\ foo: ?*struct_Foo,
201 \\};
202 });
203
204 cases.add_2("double define struct",
205 \\typedef struct Bar Bar;
206 \\typedef struct Foo Foo;
207 \\
208 \\struct Foo {
209 \\ Foo *a;
210 \\};
211 \\
212 \\struct Bar {
213 \\ Foo *a;
214 \\};
215 , &[_][]const u8{
216 \\pub const struct_Bar = extern struct {
217 \\ a: [*c]Foo,
218 \\};
219 \\pub const Bar = struct_Bar;
220 \\pub const struct_Foo = extern struct {
221 \\ a: [*c]Foo,
222 \\};
223 \\pub const Foo = struct_Foo;
224 });
225
226 cases.add_2("simple struct",
227 \\struct Foo {
228 \\ int x;
229 \\ char *y;
230 \\};
231 , &[_][]const u8{
232 \\const struct_Foo = extern struct {
233 \\ x: c_int,
234 \\ y: [*c]u8,
235 \\};
236 });
237
238 cases.add_2("self referential struct with function pointer",
239 \\struct Foo {
240 \\ void (*derp)(struct Foo *foo);
241 \\};
242 , &[_][]const u8{
243 \\pub const struct_Foo = extern struct {
244 \\ derp: ?extern fn ([*c]struct_Foo) void,
245 \\};
246 });
247 cases.add_2("struct prototype used in func",
248 \\struct Foo;
249 \\struct Foo *some_func(struct Foo *foo, int x);
250 , &[_][]const u8{
251 \\pub const struct_Foo = @OpaqueType();
252 \\pub extern fn some_func(foo: ?*struct_Foo, x: c_int) ?*struct_Foo;
253 });
254
189 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////255 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
190256
191 cases.add("typedef of function in struct field",257 cases.add_both("typedef of function in struct field",
192 \\typedef void lws_callback_function(void);258 \\typedef void lws_callback_function(void);
193 \\struct Foo {259 \\struct Foo {
194 \\ void (*func)(void);260 \\ void (*func)(void);