authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-14 13:12:39-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2019-12-14 13:12:39-05:00
log33d9dda5584a6c21df1a4d14ab1a251772f76d4d
treeeb638d75d3f4934639e63c8d58c0bee83c626ce3
parent21a85d4fb643cf14cf4afbcfc7ecfd359b910097
parent4dae70e702f10c385be1dea552f3d6e815dc93c9
signature Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #3906 from Vexu/translate-c-2

Translate-c-2 structs and unions

3 files changed, 424 insertions(+), 34 deletions(-)

src-self-hosted/clang.zig+14-1
......@@ -709,6 +709,10 @@ pub const ZigClangStringLiteral_StringKind = extern enum {
709709 UTF32,
710710};
711711
712pub const ZigClangRecordDecl_field_iterator = extern struct {
713 opaque: *c_void,
714};
715
712716pub extern fn ZigClangSourceManager_getSpellingLoc(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) struct_ZigClangSourceLocation;
713717pub extern fn ZigClangSourceManager_getFilename(self: *const struct_ZigClangSourceManager, SpellingLoc: struct_ZigClangSourceLocation) ?[*:0]const u8;
714718pub extern fn ZigClangSourceManager_getSpellingLineNumber(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint;
......@@ -718,7 +722,7 @@ pub extern fn ZigClangASTContext_getPointerType(self: ?*const struct_ZigClangAST
718722pub extern fn ZigClangASTUnit_getASTContext(self: ?*struct_ZigClangASTUnit) ?*struct_ZigClangASTContext;
719723pub extern fn ZigClangASTUnit_getSourceManager(self: *struct_ZigClangASTUnit) *struct_ZigClangSourceManager;
720724pub 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;
725pub extern fn ZigClangRecordType_getDecl(record_ty: ?*const struct_ZigClangRecordType) *const struct_ZigClangRecordDecl;
722726pub extern fn ZigClangEnumType_getDecl(record_ty: ?*const struct_ZigClangEnumType) ?*const struct_ZigClangEnumDecl;
723727pub extern fn ZigClangRecordDecl_getCanonicalDecl(record_decl: ?*const struct_ZigClangRecordDecl) ?*const struct_ZigClangTagDecl;
724728pub extern fn ZigClangEnumDecl_getCanonicalDecl(self: ?*const struct_ZigClangEnumDecl) ?*const struct_ZigClangTagDecl;
......@@ -732,6 +736,11 @@ pub extern fn ZigClangDecl_getLocation(self: *const ZigClangDecl) ZigClangSource
732736pub extern fn ZigClangRecordDecl_isUnion(record_decl: ?*const struct_ZigClangRecordDecl) bool;
733737pub extern fn ZigClangRecordDecl_isStruct(record_decl: ?*const struct_ZigClangRecordDecl) bool;
734738pub extern fn ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl: ?*const struct_ZigClangRecordDecl) bool;
739pub extern fn ZigClangRecordDecl_field_begin(*const struct_ZigClangRecordDecl) ZigClangRecordDecl_field_iterator;
740pub extern fn ZigClangRecordDecl_field_end(*const struct_ZigClangRecordDecl) ZigClangRecordDecl_field_iterator;
741pub extern fn ZigClangRecordDecl_field_iterator_next(ZigClangRecordDecl_field_iterator) ZigClangRecordDecl_field_iterator;
742pub extern fn ZigClangRecordDecl_field_iterator_deref(ZigClangRecordDecl_field_iterator) *const struct_ZigClangFieldDecl;
743pub extern fn ZigClangRecordDecl_field_iterator_neq(ZigClangRecordDecl_field_iterator, ZigClangRecordDecl_field_iterator) bool;
735744pub extern fn ZigClangEnumDecl_getIntegerType(self: ?*const struct_ZigClangEnumDecl) struct_ZigClangQualType;
736745pub extern fn ZigClangDecl_getName_bytes_begin(decl: ?*const struct_ZigClangDecl) [*c]const u8;
737746pub extern fn ZigClangSourceLocation_eq(a: struct_ZigClangSourceLocation, b: struct_ZigClangSourceLocation) bool;
......@@ -987,3 +996,7 @@ pub extern fn ZigClangStringLiteral_getKind(*const ZigClangStringLiteral) ZigCla
987996pub extern fn ZigClangStringLiteral_getString_bytes_begin_size(*const ZigClangStringLiteral, *usize) [*c]const u8;
988997
989998pub extern fn ZigClangParenExpr_getSubExpr(*const ZigClangParenExpr) *const ZigClangExpr;
999
1000pub extern fn ZigClangFieldDecl_isBitField(*const struct_ZigClangFieldDecl) bool;
1001pub extern fn ZigClangFieldDecl_getType(*const struct_ZigClangFieldDecl) struct_ZigClangQualType;
1002pub extern fn ZigClangFieldDecl_getLocation(*const struct_ZigClangFieldDecl) struct_ZigClangSourceLocation;
src-self-hosted/translate_c.zig+366-25
......@@ -31,6 +31,12 @@ fn addrEql(a: usize, b: usize) bool {
3131 return a == b;
3232}
3333
34const SymbolTable = std.StringHashMap(void);
35const AliasList = std.SegmentedList(struct {
36 alias: []const u8,
37 name: []const u8,
38}, 4);
39
3440const Scope = struct {
3541 id: Id,
3642 parent: ?*Scope,
......@@ -98,6 +104,8 @@ const Context = struct {
98104 err: Error,
99105 source_manager: *ZigClangSourceManager,
100106 decl_table: DeclTable,
107 alias_list: AliasList,
108 sym_table: SymbolTable,
101109 global_scope: *Scope.Root,
102110 ptr_params: std.BufSet,
103111 clang_context: *ZigClangASTContext,
......@@ -177,6 +185,8 @@ pub fn translate(
177185 .source_manager = ZigClangASTUnit_getSourceManager(ast_unit),
178186 .err = undefined,
179187 .decl_table = DeclTable.init(arena),
188 .alias_list = AliasList.init(arena),
189 .sym_table = SymbolTable.init(arena),
180190 .global_scope = try arena.create(Scope.Root),
181191 .ptr_params = std.BufSet.init(arena),
182192 .clang_context = ZigClangASTUnit_getASTContext(ast_unit).?,
......@@ -191,6 +201,12 @@ pub fn translate(
191201 if (!ZigClangASTUnit_visitLocalTopLevelDecls(ast_unit, &context, declVisitorC)) {
192202 return context.err;
193203 }
204 var it = context.alias_list.iterator(0);
205 while (it.next()) |alias| {
206 if (!context.sym_table.contains(alias.alias)) {
207 try createAlias(&context, alias);
208 }
209 }
194210
195211 tree.root_node.eof_token = try appendToken(&context, .Eof, "");
196212 tree.source = source_buffer.toOwnedSlice();
......@@ -220,13 +236,13 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void {
220236 return visitFnDecl(c, @ptrCast(*const ZigClangFunctionDecl, decl));
221237 },
222238 .Typedef => {
223 try resolveTypeDef(c, @ptrCast(*const ZigClangTypedefNameDecl, decl));
239 return resolveTypeDef(c, @ptrCast(*const ZigClangTypedefNameDecl, decl));
224240 },
225241 .Enum => {
226242 try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for enums", .{});
227243 },
228244 .Record => {
229 try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for structs", .{});
245 return resolveRecordDecl(c, @ptrCast(*const ZigClangRecordDecl, decl));
230246 },
231247 .Var => {
232248 return visitVarDecl(c, @ptrCast(*const ZigClangVarDecl, decl));
......@@ -398,9 +414,7 @@ fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Err
398414 const typedef_loc = ZigClangTypedefNameDecl_getLocation(typedef_decl);
399415 const type_node = transQualType(rp, child_qt, typedef_loc) catch |err| switch (err) {
400416 error.UnsupportedType => {
401 const node = try 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;
417 return failDecl(c, typedef_loc, typedef_name, "unable to resolve typedef child type", .{});
404418 },
405419 error.OutOfMemory => |e| return e,
406420 };
......@@ -426,6 +440,89 @@ fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Err
426440 try addTopLevelDecl(c, typedef_name, &node.base);
427441}
428442
443fn resolveRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!void {
444 if (try c.decl_table.put(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)), {})) |_| return; // Avoid processing this decl twice
445 const rp = makeRestorePoint(c);
446
447 const bare_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, record_decl)));
448
449 const container_kind_name = if (ZigClangRecordDecl_isUnion(record_decl))
450 "union"
451 else if (ZigClangRecordDecl_isStruct(record_decl))
452 "struct"
453 else
454 return failDecl(c, ZigClangRecordDecl_getLocation(record_decl), bare_name, "record {} is not a struct or union", .{bare_name});
455
456 if (ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl) or bare_name.len == 0)
457 return;
458
459 const visib_tok = try appendToken(c, .Keyword_pub, "pub");
460 const const_tok = try appendToken(c, .Keyword_const, "const");
461
462 const name = try std.fmt.allocPrint(c.a(), "{}_{}", .{ container_kind_name, bare_name });
463 const name_tok = try appendToken(c, .Identifier, name);
464
465 const eq_tok = try appendToken(c, .Equal, "=");
466 const init_node = transRecordDecl(c, record_decl) catch |err| switch (err) {
467 error.UnsupportedType => {
468 return failDecl(c, ZigClangRecordDecl_getLocation(record_decl), name, "unable to resolve record type", .{});
469 },
470 error.OutOfMemory => |e| return e,
471 };
472 const semicolon_token = try appendToken(c, .Semicolon, ";");
473
474 const node = try c.a().create(ast.Node.VarDecl);
475 node.* = ast.Node.VarDecl{
476 .base = ast.Node{ .id = .VarDecl },
477 .doc_comments = null,
478 .visib_token = visib_tok,
479 .thread_local_token = null,
480 .name_token = name_tok,
481 .eq_token = eq_tok,
482 .mut_token = const_tok,
483 .comptime_token = null,
484 .extern_export_token = null,
485 .lib_name = null,
486 .type_node = null,
487 .align_node = null,
488 .section_node = null,
489 .init_node = init_node,
490 .semicolon_token = semicolon_token,
491 };
492
493 try addTopLevelDecl(c, name, &node.base);
494 try c.alias_list.push(.{ .alias = bare_name, .name = name });
495}
496
497fn createAlias(c: *Context, alias: var) !void {
498 const visib_tok = try appendToken(c, .Keyword_pub, "pub");
499 const mut_tok = try appendToken(c, .Keyword_const, "const");
500 const name_tok = try appendToken(c, .Identifier, alias.alias);
501
502 const eq_tok = try appendToken(c, .Equal, "=");
503 const init_node = try appendIdentifier(c, alias.name);
504
505 const node = try c.a().create(ast.Node.VarDecl);
506 node.* = ast.Node.VarDecl{
507 .base = ast.Node{ .id = .VarDecl },
508 .doc_comments = null,
509 .visib_token = visib_tok,
510 .thread_local_token = null,
511 .name_token = name_tok,
512 .eq_token = eq_tok,
513 .mut_token = mut_tok,
514 .comptime_token = null,
515 .extern_export_token = null,
516 .lib_name = null,
517 .type_node = null,
518 .align_node = null,
519 .section_node = null,
520 .init_node = init_node,
521 .semicolon_token = try appendToken(c, .Semicolon, ";"),
522 };
523 return addTopLevelDecl(c, alias.alias, &node.base);
524}
525
429526const ResultUsed = enum {
430527 used,
431528 unused,
......@@ -442,7 +539,7 @@ fn transStmt(
442539 stmt: *const ZigClangStmt,
443540 result_used: ResultUsed,
444541 lrvalue: LRValue,
445) !TransResult {
542) TransError!TransResult {
446543 const sc = ZigClangStmt_getStmtClass(stmt);
447544 switch (sc) {
448545 .BinaryOperatorClass => return transBinaryOperator(rp, scope, @ptrCast(*const ZigClangBinaryOperator, stmt), result_used),
......@@ -456,6 +553,7 @@ fn transStmt(
456553 .StringLiteralClass => return transStringLiteral(rp, scope, @ptrCast(*const ZigClangStringLiteral, stmt), result_used),
457554 .ParenExprClass => return transExpr(rp, scope, ZigClangParenExpr_getSubExpr(@ptrCast(*const ZigClangParenExpr, stmt)), result_used, lrvalue),
458555 .InitListExprClass => return transInitListExpr(rp, scope, @ptrCast(*const ZigClangInitListExpr, stmt), result_used),
556 .ImplicitValueInitExprClass => return transImplicitValueInitExpr(rp, scope, @ptrCast(*const ZigClangExpr, stmt), result_used),
459557 else => {
460558 return revertAndWarn(
461559 rp,
......@@ -800,6 +898,13 @@ fn transImplicitCastExpr(
800898 .LValueToRValue, .NoOp => {
801899 return transExpr(rp, scope, sub_expr, .used, .r_value);
802900 },
901 .NullToPointer => {
902 return TransResult{
903 .node = try transCreateNodeNullLiteral(rp.c),
904 .node_scope = scope,
905 .child_scope = scope,
906 };
907 },
803908 else => |kind| return revertAndWarn(
804909 rp,
805910 error.UnsupportedTranslation,
......@@ -984,21 +1089,33 @@ fn transInitListExpr(
9841089 expr: *const ZigClangInitListExpr,
9851090 used: ResultUsed,
9861091) TransError!TransResult {
987 // TODO use anon literals once they work properly
9881092 const qt = getExprQualType(rp.c, @ptrCast(*const ZigClangExpr, expr));
9891093 const qual_type = ZigClangQualType_getTypePtr(qt);
9901094 const source_loc = ZigClangExpr_getBeginLoc(@ptrCast(*const ZigClangExpr, expr));
1095 switch (ZigClangType_getTypeClass(qual_type)) {
1096 .ConstantArray => {},
1097 .Record, .Elaborated => {
1098 return revertAndWarn(rp, error.UnsupportedType, source_loc, "TODO initListExpr for structs", .{});
1099 },
1100 else => {
1101 const type_name = rp.c.str(ZigClangType_getTypeClassName(qual_type));
1102 return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported initlist type: '{}'", .{type_name});
1103 },
1104 }
1105
9911106 const arr_type = ZigClangType_getAsArrayTypeUnsafe(qual_type);
9921107 const child_qt = ZigClangArrayType_getElementType(arr_type);
9931108 const init_count = ZigClangInitListExpr_getNumInits(expr);
994 const all_count = 200; //ZigClangArrayType_getSize(arr_type);
1109 const const_arr_ty = @ptrCast(*const ZigClangConstantArrayType, qual_type);
1110 const size_ap_int = ZigClangConstantArrayType_getSize(const_arr_ty);
1111 const all_count = ZigClangAPInt_getLimitedValue(size_ap_int, std.math.maxInt(usize));
9951112 const leftover_count = all_count - init_count;
9961113
9971114 var init_node: *ast.Node.SuffixOp = undefined;
9981115 var cat_tok: ast.TokenIndex = undefined;
9991116 if (init_count != 0) {
1000 var type_node = try transQualType(rp, qt, source_loc);
1001 init_node = try transCreateNodeArrayInitializer(rp.c, type_node);
1117 const dot_tok = try appendToken(rp.c, .Period, ".");
1118 init_node = try transCreateNodeArrayInitializer(rp.c, dot_tok);
10021119 var i: c_uint = 0;
10031120 while (i < init_count) : (i += 1) {
10041121 const elem_expr = ZigClangInitListExpr_getInit(expr, i);
......@@ -1016,8 +1133,8 @@ fn transInitListExpr(
10161133 cat_tok = try appendToken(rp.c, .PlusPlus, "++");
10171134 }
10181135
1019 var filler_type_node = try transQualType(rp, qt, source_loc);
1020 var filler_init_node = try transCreateNodeArrayInitializer(rp.c, filler_type_node);
1136 const dot_tok = try appendToken(rp.c, .Period, ".");
1137 var filler_init_node = try transCreateNodeArrayInitializer(rp.c, dot_tok);
10211138 const filler_val_expr = ZigClangInitListExpr_getArrayFiller(expr);
10221139 try filler_init_node.op.ArrayInitializer.push((try transExpr(rp, scope, filler_val_expr, .used, .r_value)).node);
10231140 filler_init_node.rtoken = try appendToken(rp.c, .RBrace, "}");
......@@ -1060,6 +1177,58 @@ fn transInitListExpr(
10601177 };
10611178}
10621179
1180fn transImplicitValueInitExpr(
1181 rp: RestorePoint,
1182 scope: *Scope,
1183 expr: *const ZigClangExpr,
1184 used: ResultUsed,
1185) TransError!TransResult {
1186 const source_loc = ZigClangExpr_getBeginLoc(expr);
1187 const qt = getExprQualType(rp.c, expr);
1188 const ty = ZigClangQualType_getTypePtr(qt);
1189 const node = switch (ZigClangType_getTypeClass(ty)) {
1190 .Builtin => blk: {
1191 const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty);
1192 switch (ZigClangBuiltinType_getKind(builtin_ty)) {
1193 .Bool => {
1194 break :blk try transCreateNodeBoolLiteral(rp.c, false);
1195 },
1196 .Char_U,
1197 .UChar,
1198 .Char_S,
1199 .Char8,
1200 .SChar,
1201 .UShort,
1202 .UInt,
1203 .ULong,
1204 .ULongLong,
1205 .Short,
1206 .Int,
1207 .Long,
1208 .LongLong,
1209 .UInt128,
1210 .Int128,
1211 .Float,
1212 .Double,
1213 .Float128,
1214 .Float16,
1215 .LongDouble,
1216 => {
1217 break :blk try transCreateNodeInt(rp.c, 0);
1218 },
1219 else => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported builtin type", .{}),
1220 }
1221 },
1222 .Pointer => try transCreateNodeNullLiteral(rp.c),
1223 else => return revertAndWarn(rp, error.UnsupportedType, source_loc, "type does not have an implicit init value", .{}),
1224 };
1225 return TransResult{
1226 .node = node,
1227 .child_scope = scope,
1228 .node_scope = scope,
1229 };
1230}
1231
10631232fn findBlockScope(inner: *Scope) *Scope.Block {
10641233 var scope = inner;
10651234 while (true) : (scope = scope.parent orelse unreachable) {
......@@ -1142,28 +1311,120 @@ fn maybeSuppressResult(
11421311
11431312fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: *ast.Node) !void {
11441313 try c.tree.root_node.decls.push(decl_node);
1314 _ = try c.sym_table.put(name, {});
11451315}
11461316
11471317fn transQualType(rp: RestorePoint, qt: ZigClangQualType, source_loc: ZigClangSourceLocation) TypeError!*ast.Node {
11481318 return transType(rp, ZigClangQualType_getTypePtr(qt), source_loc);
11491319}
11501320
1321fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) TypeError!*ast.Node {
1322 const rp = makeRestorePoint(c);
1323
1324 const record_loc = ZigClangRecordDecl_getLocation(record_decl);
1325
1326 var container_kind_name: []const u8 = undefined;
1327 var container_kind: std.zig.Token.Id = undefined;
1328
1329 if (ZigClangRecordDecl_isUnion(record_decl)) {
1330 container_kind_name = "union";
1331 container_kind = .Keyword_union;
1332 } else if (ZigClangRecordDecl_isStruct(record_decl)) {
1333 container_kind_name = "struct";
1334 container_kind = .Keyword_struct;
1335 } else {
1336 return revertAndWarn(
1337 rp,
1338 error.UnsupportedType,
1339 record_loc,
1340 "unsupported record type",
1341 .{},
1342 );
1343 }
1344
1345 const record_def = ZigClangRecordDecl_getDefinition(record_decl) orelse {
1346 return transCreateNodeOpaqueType(c);
1347 };
1348
1349 const extern_tok = try appendToken(c, .Keyword_extern, "extern");
1350 const container_tok = try appendToken(c, container_kind, container_kind_name);
1351 const lbrace_token = try appendToken(c, .LBrace, "{");
1352
1353 const container_node = try c.a().create(ast.Node.ContainerDecl);
1354 container_node.* = .{
1355 .base = ast.Node{ .id = .ContainerDecl },
1356 .layout_token = extern_tok,
1357 .kind_token = container_tok,
1358 .init_arg_expr = .None,
1359 .fields_and_decls = ast.Node.ContainerDecl.DeclList.init(c.a()),
1360 .lbrace_token = lbrace_token,
1361 .rbrace_token = undefined,
1362 };
1363
1364 var it = ZigClangRecordDecl_field_begin(record_def);
1365 const end_it = ZigClangRecordDecl_field_end(record_def);
1366 while (ZigClangRecordDecl_field_iterator_neq(it, end_it)) : (it = ZigClangRecordDecl_field_iterator_next(it)) {
1367 const field_decl = ZigClangRecordDecl_field_iterator_deref(it);
1368 const field_loc = ZigClangFieldDecl_getLocation(field_decl);
1369
1370 if (ZigClangFieldDecl_isBitField(field_decl)) {
1371 rp.activate();
1372 const node = try transCreateNodeOpaqueType(c);
1373 try emitWarning(c, field_loc, "{} demoted to opaque type - has bitfield", .{container_kind_name});
1374 return node;
1375 }
1376
1377 const field_name = try appendToken(c, .Identifier, try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, field_decl))));
1378 _ = try appendToken(c, .Colon, ":");
1379 const field_type = try transQualType(rp, ZigClangFieldDecl_getType(field_decl), field_loc);
1380
1381 const field_node = try c.a().create(ast.Node.ContainerField);
1382 field_node.* = .{
1383 .doc_comments = null,
1384 .comptime_token = null,
1385 .name_token = field_name,
1386 .type_expr = field_type,
1387 .value_expr = null,
1388 .align_expr = null,
1389 };
1390
1391 try container_node.fields_and_decls.push(&field_node.base);
1392 _ = try appendToken(c, .Comma, ",");
1393 }
1394
1395 container_node.rbrace_token = try appendToken(c, .RBrace, "}");
1396 return &container_node.base;
1397}
1398
11511399fn qualTypeIsPtr(qt: ZigClangQualType) bool {
11521400 return ZigClangType_getTypeClass(qualTypeCanon(qt)) == .Pointer;
11531401}
11541402
11551403fn qualTypeChildIsFnProto(qt: ZigClangQualType) bool {
11561404 const ty = ZigClangQualType_getTypePtr(qt);
1157 if (ZigClangType_getTypeClass(ty) == .Paren) {
1158 const paren_type = @ptrCast(*const ZigClangParenType, ty);
1159 const inner_type = ZigClangParenType_getInnerType(paren_type);
1160 return ZigClangQualType_getTypeClass(inner_type) == .FunctionProto;
1161 }
1162 if (ZigClangType_getTypeClass(ty) == .Attributed) {
1163 const attr_type = @ptrCast(*const ZigClangAttributedType, ty);
1164 return qualTypeChildIsFnProto(ZigClangAttributedType_getEquivalentType(attr_type));
1405
1406 switch (ZigClangType_getTypeClass(ty)) {
1407 .FunctionProto, .FunctionNoProto => return true,
1408 .Elaborated => {
1409 const elaborated_ty = @ptrCast(*const ZigClangElaboratedType, ty);
1410 return qualTypeChildIsFnProto(ZigClangElaboratedType_getNamedType(elaborated_ty));
1411 },
1412 .Typedef => {
1413 const typedef_ty = @ptrCast(*const ZigClangTypedefType, ty);
1414 const typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
1415 return qualTypeChildIsFnProto(ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl));
1416 },
1417 .Paren => {
1418 const paren_type = @ptrCast(*const ZigClangParenType, ty);
1419 const inner_type = ZigClangParenType_getInnerType(paren_type);
1420 return ZigClangQualType_getTypeClass(inner_type) == .FunctionProto;
1421 },
1422 .Attributed => {
1423 const attr_type = @ptrCast(*const ZigClangAttributedType, ty);
1424 return qualTypeChildIsFnProto(ZigClangAttributedType_getEquivalentType(attr_type));
1425 },
1426 else => return false,
11651427 }
1166 return false;
11671428}
11681429
11691430fn qualTypeCanon(qt: ZigClangQualType) *const ZigClangType {
......@@ -1197,7 +1458,18 @@ fn typeIsOpaque(c: *Context, ty: *const ZigClangType, loc: ZigClangSourceLocatio
11971458 .Record => {
11981459 const record_ty = @ptrCast(*const ZigClangRecordType, ty);
11991460 const record_decl = ZigClangRecordType_getDecl(record_ty);
1200 return (ZigClangRecordDecl_getDefinition(record_decl) == null);
1461 const record_def = ZigClangRecordDecl_getDefinition(record_decl) orelse
1462 return true;
1463 var it = ZigClangRecordDecl_field_begin(record_def);
1464 const end_it = ZigClangRecordDecl_field_end(record_def);
1465 while (ZigClangRecordDecl_field_iterator_neq(it, end_it)) : (it = ZigClangRecordDecl_field_iterator_next(it)) {
1466 const field_decl = ZigClangRecordDecl_field_iterator_deref(it);
1467
1468 if (ZigClangFieldDecl_isBitField(field_decl)) {
1469 return true;
1470 }
1471 }
1472 return false;
12011473 },
12021474 .Elaborated => {
12031475 const elaborated_ty = @ptrCast(*const ZigClangElaboratedType, ty);
......@@ -1435,12 +1707,35 @@ fn transCreateNodeUndefinedLiteral(c: *Context) !*ast.Node {
14351707 return &node.base;
14361708}
14371709
1438fn transCreateNodeArrayInitializer(c: *Context, type_node: *ast.Node) !*ast.Node.SuffixOp {
1710fn transCreateNodeNullLiteral(c: *Context) !*ast.Node {
1711 const token = try appendToken(c, .Keyword_null, "null");
1712 const node = try c.a().create(ast.Node.NullLiteral);
1713 node.* = ast.Node.NullLiteral{
1714 .base = ast.Node{ .id = .NullLiteral },
1715 .token = token,
1716 };
1717 return &node.base;
1718}
1719
1720fn transCreateNodeBoolLiteral(c: *Context, value: bool) !*ast.Node {
1721 const token = if (value)
1722 try appendToken(c, .Keyword_true, "true")
1723 else
1724 try appendToken(c, .Keyword_false, "false");
1725 const node = try c.a().create(ast.Node.BoolLiteral);
1726 node.* = ast.Node.BoolLiteral{
1727 .base = ast.Node{ .id = .BoolLiteral },
1728 .token = token,
1729 };
1730 return &node.base;
1731}
1732
1733fn transCreateNodeArrayInitializer(c: *Context, dot_tok: ast.TokenIndex) !*ast.Node.SuffixOp {
14391734 _ = try appendToken(c, .LBrace, "{");
14401735 const node = try c.a().create(ast.Node.SuffixOp);
14411736 node.* = ast.Node.SuffixOp{
14421737 .base = ast.Node{ .id = .SuffixOp },
1443 .lhs = .{ .node = type_node },
1738 .lhs = .{ .dot = dot_tok },
14441739 .op = .{
14451740 .ArrayInitializer = ast.Node.SuffixOp.Op.InitList.init(c.a()),
14461741 },
......@@ -1450,7 +1745,7 @@ fn transCreateNodeArrayInitializer(c: *Context, type_node: *ast.Node) !*ast.Node
14501745}
14511746
14521747fn transCreateNodeInt(c: *Context, int: var) !*ast.Node {
1453 const token = try appendToken(c, .IntegerLiteral, try std.fmt.allocPrint(c.a(), "{}", .{int}));
1748 const token = try appendTokenFmt(c, .IntegerLiteral, "{}", .{int});
14541749 const node = try c.a().create(ast.Node.IntegerLiteral);
14551750 node.* = ast.Node.IntegerLiteral{
14561751 .base = ast.Node{ .id = .IntegerLiteral },
......@@ -1459,6 +1754,21 @@ fn transCreateNodeInt(c: *Context, int: var) !*ast.Node {
14591754 return &node.base;
14601755}
14611756
1757fn transCreateNodeOpaqueType(c: *Context) !*ast.Node {
1758 const builtin_tok = try appendToken(c, .Builtin, "@OpaqueType");
1759 _ = try appendToken(c, .LParen, "(");
1760 const rparen_tok = try appendToken(c, .RParen, ")");
1761
1762 const call_node = try c.a().create(ast.Node.BuiltinCall);
1763 call_node.* = ast.Node.BuiltinCall{
1764 .base = ast.Node{ .id = ast.Node.Id.BuiltinCall },
1765 .builtin_token = builtin_tok,
1766 .params = ast.Node.BuiltinCall.ParamList.init(c.a()),
1767 .rparen_token = rparen_tok,
1768 };
1769 return &call_node.base;
1770}
1771
14621772const RestorePoint = struct {
14631773 c: *Context,
14641774 token_index: ast.TokenIndex,
......@@ -1583,6 +1893,19 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
15831893 const typedef_name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, typedef_decl)));
15841894 return appendIdentifier(rp.c, typedef_name);
15851895 },
1896 .Record => {
1897 const record_ty = @ptrCast(*const ZigClangRecordType, ty);
1898
1899 const record_decl = ZigClangRecordType_getDecl(record_ty);
1900 if (try getContainerName(rp.c, record_decl)) |name|
1901 return appendIdentifier(rp.c, name)
1902 else
1903 return transRecordDecl(rp.c, record_decl);
1904 },
1905 .Elaborated => {
1906 const elaborated_ty = @ptrCast(*const ZigClangElaboratedType, ty);
1907 return transQualType(rp, ZigClangElaboratedType_getNamedType(elaborated_ty), source_loc);
1908 },
15861909 else => {
15871910 const type_name = rp.c.str(ZigClangType_getTypeClassName(ty));
15881911 return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported type: '{}'", .{type_name});
......@@ -1590,6 +1913,24 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
15901913 }
15911914}
15921915
1916fn getContainerName(c: *Context, record_decl: *const ZigClangRecordDecl) !?[]const u8 {
1917 const bare_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, record_decl)));
1918
1919 const container_kind_name = if (ZigClangRecordDecl_isUnion(record_decl))
1920 "union"
1921 else if (ZigClangRecordDecl_isStruct(record_decl))
1922 "struct"
1923 else {
1924 try emitWarning(c, ZigClangRecordDecl_getLocation(record_decl), "record {} is not a struct or union", .{bare_name});
1925 return null;
1926 };
1927
1928 if (ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl) or bare_name.len == 0)
1929 return null;
1930
1931 return try std.fmt.allocPrint(c.a(), "{}_{}", .{ container_kind_name, bare_name });
1932}
1933
15931934fn isCVoid(qt: ZigClangQualType) bool {
15941935 const ty = ZigClangQualType_getTypePtr(qt);
15951936 if (ZigClangType_getTypeClass(ty) == .Builtin) {
test/translate_c.zig+44-8
......@@ -186,9 +186,40 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
186186 \\pub export var arr2: [*c]u8 = "hello";
187187 });
188188
189 cases.add_2("array initializer expr",
190 \\static void foo(void){
191 \\ char arr[10] ={1};
192 \\ char *arr1[10] ={0};
193 \\}
194 , &[_][]const u8{
195 \\pub fn foo() void {
196 \\ var arr: [10]u8 = .{
197 \\ @as(u8, 1),
198 \\ } ++ .{0} ** 9;
199 \\ var arr1: [10][*c]u8 = .{
200 \\ null,
201 \\ } ++ .{null} ** 9;
202 \\}
203 });
204
205 cases.add_2("field struct",
206 \\union OpenGLProcs {
207 \\ struct {
208 \\ int Clear;
209 \\ } gl;
210 \\};
211 , &[_][]const u8{
212 \\pub const union_OpenGLProcs = extern union {
213 \\ gl: extern struct {
214 \\ Clear: c_int,
215 \\ },
216 \\};
217 \\pub const OpenGLProcs = union_OpenGLProcs;
218 });
219
189220 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
190221
191 cases.add("typedef of function in struct field",
222 cases.add_both("typedef of function in struct field",
192223 \\typedef void lws_callback_function(void);
193224 \\struct Foo {
194225 \\ void (*func)(void);
......@@ -202,7 +233,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
202233 \\};
203234 });
204235
205 cases.add("pointer to struct demoted to opaque due to bit fields",
236 cases.add_both("pointer to struct demoted to opaque due to bit fields",
206237 \\struct Foo {
207238 \\ unsigned int: 1;
208239 \\};
......@@ -210,7 +241,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
210241 \\ struct Foo *foo;
211242 \\};
212243 , &[_][]const u8{
213 \\pub const struct_Foo = @OpaqueType();
244 \\pub const struct_Foo = @OpaqueType()
245 ,
214246 \\pub const struct_Bar = extern struct {
215247 \\ foo: ?*struct_Foo,
216248 \\};
......@@ -359,7 +391,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
359391 \\}
360392 });
361393
362 cases.add("double define struct",
394 cases.add_both("double define struct",
363395 \\typedef struct Bar Bar;
364396 \\typedef struct Foo Foo;
365397 \\
......@@ -374,10 +406,14 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
374406 \\pub const struct_Foo = extern struct {
375407 \\ a: [*c]Foo,
376408 \\};
409 ,
377410 \\pub const Foo = struct_Foo;
411 ,
378412 \\pub const struct_Bar = extern struct {
379413 \\ a: [*c]Foo,
380414 \\};
415 ,
416 \\pub const Bar = struct_Bar;
381417 });
382418
383419 cases.addAllowWarnings("simple data types",
......@@ -454,7 +490,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
454490 \\pub extern fn foo(noalias bar: ?*c_void, noalias arg1: ?*c_void) void;
455491 });
456492
457 cases.add("simple struct",
493 cases.add_both("simple struct",
458494 \\struct Foo {
459495 \\ int x;
460496 \\ char *y;
......@@ -506,7 +542,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
506542 \\pub extern fn func(array: [*c]c_int) void;
507543 });
508544
509 cases.add("self referential struct with function pointer",
545 cases.add_both("self referential struct with function pointer",
510546 \\struct Foo {
511547 \\ void (*derp)(struct Foo *foo);
512548 \\};
......@@ -518,7 +554,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
518554 \\pub const Foo = struct_Foo;
519555 });
520556
521 cases.add("struct prototype used in func",
557 cases.add_both("struct prototype used in func",
522558 \\struct Foo;
523559 \\struct Foo *some_func(struct Foo *foo, int x);
524560 , &[_][]const u8{
......@@ -550,7 +586,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
550586 \\pub const THING2 = THING1;
551587 });
552588
553 cases.add("circular struct definitions",
589 cases.add_both("circular struct definitions",
554590 \\struct Bar;
555591 \\
556592 \\struct Foo {