| ... | ... | @@ -31,6 +31,12 @@ fn addrEql(a: usize, b: usize) bool { |
| 31 | 31 | return a == b; |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | const SymbolTable = std.StringHashMap(void); |
| 35 | const AliasList = std.SegmentedList(struct { |
| 36 | alias: []const u8, |
| 37 | name: []const u8, |
| 38 | }, 4); |
| 39 | |
| 34 | 40 | const Scope = struct { |
| 35 | 41 | id: Id, |
| 36 | 42 | parent: ?*Scope, |
| ... | ... | @@ -98,6 +104,8 @@ const Context = struct { |
| 98 | 104 | err: Error, |
| 99 | 105 | source_manager: *ZigClangSourceManager, |
| 100 | 106 | decl_table: DeclTable, |
| 107 | alias_list: AliasList, |
| 108 | sym_table: SymbolTable, |
| 101 | 109 | global_scope: *Scope.Root, |
| 102 | 110 | ptr_params: std.BufSet, |
| 103 | 111 | clang_context: *ZigClangASTContext, |
| ... | ... | @@ -177,6 +185,8 @@ pub fn translate( |
| 177 | 185 | .source_manager = ZigClangASTUnit_getSourceManager(ast_unit), |
| 178 | 186 | .err = undefined, |
| 179 | 187 | .decl_table = DeclTable.init(arena), |
| 188 | .alias_list = AliasList.init(arena), |
| 189 | .sym_table = SymbolTable.init(arena), |
| 180 | 190 | .global_scope = try arena.create(Scope.Root), |
| 181 | 191 | .ptr_params = std.BufSet.init(arena), |
| 182 | 192 | .clang_context = ZigClangASTUnit_getASTContext(ast_unit).?, |
| ... | ... | @@ -191,6 +201,12 @@ pub fn translate( |
| 191 | 201 | if (!ZigClangASTUnit_visitLocalTopLevelDecls(ast_unit, &context, declVisitorC)) { |
| 192 | 202 | return context.err; |
| 193 | 203 | } |
| 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 | } |
| 194 | 210 | |
| 195 | 211 | tree.root_node.eof_token = try appendToken(&context, .Eof, ""); |
| 196 | 212 | tree.source = source_buffer.toOwnedSlice(); |
| ... | ... | @@ -220,13 +236,13 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void { |
| 220 | 236 | return visitFnDecl(c, @ptrCast(*const ZigClangFunctionDecl, decl)); |
| 221 | 237 | }, |
| 222 | 238 | .Typedef => { |
| 223 | | try resolveTypeDef(c, @ptrCast(*const ZigClangTypedefNameDecl, decl)); |
| 239 | return resolveTypeDef(c, @ptrCast(*const ZigClangTypedefNameDecl, decl)); |
| 224 | 240 | }, |
| 225 | 241 | .Enum => { |
| 226 | 242 | try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for enums", .{}); |
| 227 | 243 | }, |
| 228 | 244 | .Record => { |
| 229 | | try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for structs", .{}); |
| 245 | return resolveRecordDecl(c, @ptrCast(*const ZigClangRecordDecl, decl)); |
| 230 | 246 | }, |
| 231 | 247 | .Var => { |
| 232 | 248 | return visitVarDecl(c, @ptrCast(*const ZigClangVarDecl, decl)); |
| ... | ... | @@ -398,9 +414,7 @@ fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Err |
| 398 | 414 | const typedef_loc = ZigClangTypedefNameDecl_getLocation(typedef_decl); |
| 399 | 415 | const type_node = transQualType(rp, child_qt, typedef_loc) catch |err| switch (err) { |
| 400 | 416 | 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", .{}); |
| 404 | 418 | }, |
| 405 | 419 | error.OutOfMemory => |e| return e, |
| 406 | 420 | }; |
| ... | ... | @@ -426,6 +440,89 @@ fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Err |
| 426 | 440 | try addTopLevelDecl(c, typedef_name, &node.base); |
| 427 | 441 | } |
| 428 | 442 | |
| 443 | fn 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 | |
| 497 | fn 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 | |
| 429 | 526 | const ResultUsed = enum { |
| 430 | 527 | used, |
| 431 | 528 | unused, |
| ... | ... | @@ -442,7 +539,7 @@ fn transStmt( |
| 442 | 539 | stmt: *const ZigClangStmt, |
| 443 | 540 | result_used: ResultUsed, |
| 444 | 541 | lrvalue: LRValue, |
| 445 | | ) !TransResult { |
| 542 | ) TransError!TransResult { |
| 446 | 543 | const sc = ZigClangStmt_getStmtClass(stmt); |
| 447 | 544 | switch (sc) { |
| 448 | 545 | .BinaryOperatorClass => return transBinaryOperator(rp, scope, @ptrCast(*const ZigClangBinaryOperator, stmt), result_used), |
| ... | ... | @@ -456,6 +553,7 @@ fn transStmt( |
| 456 | 553 | .StringLiteralClass => return transStringLiteral(rp, scope, @ptrCast(*const ZigClangStringLiteral, stmt), result_used), |
| 457 | 554 | .ParenExprClass => return transExpr(rp, scope, ZigClangParenExpr_getSubExpr(@ptrCast(*const ZigClangParenExpr, stmt)), result_used, lrvalue), |
| 458 | 555 | .InitListExprClass => return transInitListExpr(rp, scope, @ptrCast(*const ZigClangInitListExpr, stmt), result_used), |
| 556 | .ImplicitValueInitExprClass => return transImplicitValueInitExpr(rp, scope, @ptrCast(*const ZigClangExpr, stmt), result_used), |
| 459 | 557 | else => { |
| 460 | 558 | return revertAndWarn( |
| 461 | 559 | rp, |
| ... | ... | @@ -800,6 +898,13 @@ fn transImplicitCastExpr( |
| 800 | 898 | .LValueToRValue, .NoOp => { |
| 801 | 899 | return transExpr(rp, scope, sub_expr, .used, .r_value); |
| 802 | 900 | }, |
| 901 | .NullToPointer => { |
| 902 | return TransResult{ |
| 903 | .node = try transCreateNodeNullLiteral(rp.c), |
| 904 | .node_scope = scope, |
| 905 | .child_scope = scope, |
| 906 | }; |
| 907 | }, |
| 803 | 908 | else => |kind| return revertAndWarn( |
| 804 | 909 | rp, |
| 805 | 910 | error.UnsupportedTranslation, |
| ... | ... | @@ -984,21 +1089,33 @@ fn transInitListExpr( |
| 984 | 1089 | expr: *const ZigClangInitListExpr, |
| 985 | 1090 | used: ResultUsed, |
| 986 | 1091 | ) TransError!TransResult { |
| 987 | | // TODO use anon literals once they work properly |
| 988 | 1092 | const qt = getExprQualType(rp.c, @ptrCast(*const ZigClangExpr, expr)); |
| 989 | 1093 | const qual_type = ZigClangQualType_getTypePtr(qt); |
| 990 | 1094 | 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 | |
| 991 | 1106 | const arr_type = ZigClangType_getAsArrayTypeUnsafe(qual_type); |
| 992 | 1107 | const child_qt = ZigClangArrayType_getElementType(arr_type); |
| 993 | 1108 | 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)); |
| 995 | 1112 | const leftover_count = all_count - init_count; |
| 996 | 1113 | |
| 997 | 1114 | var init_node: *ast.Node.SuffixOp = undefined; |
| 998 | 1115 | var cat_tok: ast.TokenIndex = undefined; |
| 999 | 1116 | 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); |
| 1002 | 1119 | var i: c_uint = 0; |
| 1003 | 1120 | while (i < init_count) : (i += 1) { |
| 1004 | 1121 | const elem_expr = ZigClangInitListExpr_getInit(expr, i); |
| ... | ... | @@ -1016,8 +1133,8 @@ fn transInitListExpr( |
| 1016 | 1133 | cat_tok = try appendToken(rp.c, .PlusPlus, "++"); |
| 1017 | 1134 | } |
| 1018 | 1135 | |
| 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); |
| 1021 | 1138 | const filler_val_expr = ZigClangInitListExpr_getArrayFiller(expr); |
| 1022 | 1139 | try filler_init_node.op.ArrayInitializer.push((try transExpr(rp, scope, filler_val_expr, .used, .r_value)).node); |
| 1023 | 1140 | filler_init_node.rtoken = try appendToken(rp.c, .RBrace, "}"); |
| ... | ... | @@ -1060,6 +1177,58 @@ fn transInitListExpr( |
| 1060 | 1177 | }; |
| 1061 | 1178 | } |
| 1062 | 1179 | |
| 1180 | fn 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 | |
| 1063 | 1232 | fn findBlockScope(inner: *Scope) *Scope.Block { |
| 1064 | 1233 | var scope = inner; |
| 1065 | 1234 | while (true) : (scope = scope.parent orelse unreachable) { |
| ... | ... | @@ -1142,28 +1311,120 @@ fn maybeSuppressResult( |
| 1142 | 1311 | |
| 1143 | 1312 | fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: *ast.Node) !void { |
| 1144 | 1313 | try c.tree.root_node.decls.push(decl_node); |
| 1314 | _ = try c.sym_table.put(name, {}); |
| 1145 | 1315 | } |
| 1146 | 1316 | |
| 1147 | 1317 | fn transQualType(rp: RestorePoint, qt: ZigClangQualType, source_loc: ZigClangSourceLocation) TypeError!*ast.Node { |
| 1148 | 1318 | return transType(rp, ZigClangQualType_getTypePtr(qt), source_loc); |
| 1149 | 1319 | } |
| 1150 | 1320 | |
| 1321 | fn 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 | |
| 1151 | 1399 | fn qualTypeIsPtr(qt: ZigClangQualType) bool { |
| 1152 | 1400 | return ZigClangType_getTypeClass(qualTypeCanon(qt)) == .Pointer; |
| 1153 | 1401 | } |
| 1154 | 1402 | |
| 1155 | 1403 | fn qualTypeChildIsFnProto(qt: ZigClangQualType) bool { |
| 1156 | 1404 | 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, |
| 1165 | 1427 | } |
| 1166 | | return false; |
| 1167 | 1428 | } |
| 1168 | 1429 | |
| 1169 | 1430 | fn qualTypeCanon(qt: ZigClangQualType) *const ZigClangType { |
| ... | ... | @@ -1197,7 +1458,18 @@ fn typeIsOpaque(c: *Context, ty: *const ZigClangType, loc: ZigClangSourceLocatio |
| 1197 | 1458 | .Record => { |
| 1198 | 1459 | const record_ty = @ptrCast(*const ZigClangRecordType, ty); |
| 1199 | 1460 | 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; |
| 1201 | 1473 | }, |
| 1202 | 1474 | .Elaborated => { |
| 1203 | 1475 | const elaborated_ty = @ptrCast(*const ZigClangElaboratedType, ty); |
| ... | ... | @@ -1435,12 +1707,35 @@ fn transCreateNodeUndefinedLiteral(c: *Context) !*ast.Node { |
| 1435 | 1707 | return &node.base; |
| 1436 | 1708 | } |
| 1437 | 1709 | |
| 1438 | | fn transCreateNodeArrayInitializer(c: *Context, type_node: *ast.Node) !*ast.Node.SuffixOp { |
| 1710 | fn 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 | |
| 1720 | fn 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 | |
| 1733 | fn transCreateNodeArrayInitializer(c: *Context, dot_tok: ast.TokenIndex) !*ast.Node.SuffixOp { |
| 1439 | 1734 | _ = try appendToken(c, .LBrace, "{"); |
| 1440 | 1735 | const node = try c.a().create(ast.Node.SuffixOp); |
| 1441 | 1736 | node.* = ast.Node.SuffixOp{ |
| 1442 | 1737 | .base = ast.Node{ .id = .SuffixOp }, |
| 1443 | | .lhs = .{ .node = type_node }, |
| 1738 | .lhs = .{ .dot = dot_tok }, |
| 1444 | 1739 | .op = .{ |
| 1445 | 1740 | .ArrayInitializer = ast.Node.SuffixOp.Op.InitList.init(c.a()), |
| 1446 | 1741 | }, |
| ... | ... | @@ -1450,7 +1745,7 @@ fn transCreateNodeArrayInitializer(c: *Context, type_node: *ast.Node) !*ast.Node |
| 1450 | 1745 | } |
| 1451 | 1746 | |
| 1452 | 1747 | fn 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}); |
| 1454 | 1749 | const node = try c.a().create(ast.Node.IntegerLiteral); |
| 1455 | 1750 | node.* = ast.Node.IntegerLiteral{ |
| 1456 | 1751 | .base = ast.Node{ .id = .IntegerLiteral }, |
| ... | ... | @@ -1459,6 +1754,21 @@ fn transCreateNodeInt(c: *Context, int: var) !*ast.Node { |
| 1459 | 1754 | return &node.base; |
| 1460 | 1755 | } |
| 1461 | 1756 | |
| 1757 | fn 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 | |
| 1462 | 1772 | const RestorePoint = struct { |
| 1463 | 1773 | c: *Context, |
| 1464 | 1774 | token_index: ast.TokenIndex, |
| ... | ... | @@ -1583,6 +1893,19 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour |
| 1583 | 1893 | const typedef_name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, typedef_decl))); |
| 1584 | 1894 | return appendIdentifier(rp.c, typedef_name); |
| 1585 | 1895 | }, |
| 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 | }, |
| 1586 | 1909 | else => { |
| 1587 | 1910 | const type_name = rp.c.str(ZigClangType_getTypeClassName(ty)); |
| 1588 | 1911 | 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 |
| 1590 | 1913 | } |
| 1591 | 1914 | } |
| 1592 | 1915 | |
| 1916 | fn 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 | |
| 1593 | 1934 | fn isCVoid(qt: ZigClangQualType) bool { |
| 1594 | 1935 | const ty = ZigClangQualType_getTypePtr(qt); |
| 1595 | 1936 | if (ZigClangType_getTypeClass(ty) == .Builtin) { |