authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-17 16:26:11+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-17 16:26:11+02:00
logd5fecbd0bacd986fc02c8a98aea07ac42303f0ce
tree95f8bad785c2f41e800a439635b4f57ae4470f8d
parente2974759dd62e15f04e1aeb8babee65e6ffb3413
signature Commit is signed but in an unrecognized format.

translate-c: support scoped typedef, enum and record decls

Closes #5256

3 files changed, 318 insertions(+), 169 deletions(-)

src/translate_c.zig+150-140
......@@ -433,13 +433,13 @@ fn declVisitor(c: *Context, decl: *const clang.Decl) Error!void {
433433 return visitFnDecl(c, @ptrCast(*const clang.FunctionDecl, decl));
434434 },
435435 .Typedef => {
436 _ = try transTypeDef(c, @ptrCast(*const clang.TypedefNameDecl, decl), true);
436 try transTypeDef(c, &c.global_scope.base, @ptrCast(*const clang.TypedefNameDecl, decl));
437437 },
438438 .Enum => {
439 _ = try transEnumDecl(c, @ptrCast(*const clang.EnumDecl, decl));
439 try transEnumDecl(c, &c.global_scope.base, @ptrCast(*const clang.EnumDecl, decl));
440440 },
441441 .Record => {
442 _ = try transRecordDecl(c, @ptrCast(*const clang.RecordDecl, decl));
442 try transRecordDecl(c, &c.global_scope.base, @ptrCast(*const clang.RecordDecl, decl));
443443 },
444444 .Var => {
445445 return visitVarDecl(c, @ptrCast(*const clang.VarDecl, decl), null);
......@@ -622,11 +622,11 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {
622622 return addTopLevelDecl(c, fn_name, Node.initPayload(&proto_node.base));
623623}
624624
625fn transQualTypeMaybeInitialized(c: *Context, qt: clang.QualType, decl_init: ?*const clang.Expr, loc: clang.SourceLocation) TransError!Node {
625fn transQualTypeMaybeInitialized(c: *Context, scope: *Scope, qt: clang.QualType, decl_init: ?*const clang.Expr, loc: clang.SourceLocation) TransError!Node {
626626 return if (decl_init) |init_expr|
627 transQualTypeInitialized(c, qt, init_expr, loc)
627 transQualTypeInitialized(c, scope, qt, init_expr, loc)
628628 else
629 transQualType(c, qt, loc);
629 transQualType(c, scope, qt, loc);
630630}
631631
632632/// if mangled_name is not null, this var decl was declared in a block scope.
......@@ -658,7 +658,7 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co
658658 var is_extern = storage_class == .Extern and !has_init;
659659 var is_export = !is_extern and storage_class != .Static;
660660
661 const type_node = transQualTypeMaybeInitialized(c, qual_type, decl_init, var_decl_loc) catch |err| switch (err) {
661 const type_node = transQualTypeMaybeInitialized(c, scope, qual_type, decl_init, var_decl_loc) catch |err| switch (err) {
662662 error.UnsupportedTranslation, error.UnsupportedType => {
663663 return failDecl(c, var_decl_loc, checked_name, "unable to resolve variable type", .{});
664664 },
......@@ -733,11 +733,6 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co
733733 return addTopLevelDecl(c, checked_name, node);
734734}
735735
736fn transTypeDefAsBuiltin(c: *Context, typedef_decl: *const clang.TypedefNameDecl, builtin_name: []const u8) !Node {
737 _ = try c.decl_table.put(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), builtin_name);
738 return Tag.identifier.create(c.arena, builtin_name);
739}
740
741736const builtin_typedef_map = std.ComptimeStringMap([]const u8, .{
742737 .{ "uint8_t", "u8" },
743738 .{ "int8_t", "i8" },
......@@ -753,42 +748,28 @@ const builtin_typedef_map = std.ComptimeStringMap([]const u8, .{
753748 .{ "size_t", "usize" },
754749});
755750
756fn transTypeDef(c: *Context, typedef_decl: *const clang.TypedefNameDecl, top_level_visit: bool) Error!?Node {
751fn transTypeDef(c: *Context, scope: *Scope, typedef_decl: *const clang.TypedefNameDecl) Error!void {
757752 if (c.decl_table.get(@ptrToInt(typedef_decl.getCanonicalDecl()))) |name|
758 return try Tag.identifier.create(c.arena, name); // Avoid processing this decl twice
753 return; // Avoid processing this decl twice
754 const toplevel = scope.id == .root;
755 const bs: *Scope.Block = if (!toplevel) try scope.findBlockScope(c) else undefined;
759756
760 const typedef_name = try c.str(@ptrCast(*const clang.NamedDecl, typedef_decl).getName_bytes_begin());
757 const bare_name = try c.str(@ptrCast(*const clang.NamedDecl, typedef_decl).getName_bytes_begin());
761758
762759 // TODO https://github.com/ziglang/zig/issues/3756
763760 // TODO https://github.com/ziglang/zig/issues/1802
764 const checked_name = if (isZigPrimitiveType(typedef_name)) try std.fmt.allocPrint(c.arena, "{s}_{d}", .{ typedef_name, c.getMangle() }) else typedef_name;
765 if (builtin_typedef_map.get(checked_name)) |builtin| {
766 _ = try c.decl_table.put(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), builtin);
767 return try Tag.identifier.create(c.arena, builtin);
761 var name: []const u8 = if (isZigPrimitiveType(bare_name)) try std.fmt.allocPrint(c.arena, "{s}_{d}", .{ bare_name, c.getMangle() }) else bare_name;
762 if (builtin_typedef_map.get(name)) |builtin| {
763 return c.decl_table.putNoClobber(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), builtin);
768764 }
765 if (!toplevel) name = try bs.makeMangledName(c, name);
766 try c.decl_table.putNoClobber(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), name);
769767
770 if (!top_level_visit) {
771 return try Tag.identifier.create(c.arena, checked_name);
772 }
773
774 _ = try c.decl_table.put(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), checked_name);
775 const node = (try transCreateNodeTypedef(c, typedef_decl, true, checked_name)) orelse return null;
776 try addTopLevelDecl(c, checked_name, node);
777 return try Tag.identifier.create(c.arena, checked_name);
778}
779
780fn transCreateNodeTypedef(
781 c: *Context,
782 typedef_decl: *const clang.TypedefNameDecl,
783 toplevel: bool,
784 checked_name: []const u8,
785) Error!?Node {
786768 const child_qt = typedef_decl.getUnderlyingType();
787769 const typedef_loc = typedef_decl.getLocation();
788 const init_node = transQualType(c, child_qt, typedef_loc) catch |err| switch (err) {
770 const init_node = transQualType(c, scope, child_qt, typedef_loc) catch |err| switch (err) {
789771 error.UnsupportedType => {
790 try failDecl(c, typedef_loc, checked_name, "unable to resolve typedef child type", .{});
791 return null;
772 return failDecl(c, typedef_loc, name, "unable to resolve typedef child type", .{});
792773 },
793774 error.OutOfMemory => |e| return e,
794775 };
......@@ -797,17 +778,25 @@ fn transCreateNodeTypedef(
797778 payload.* = .{
798779 .base = .{ .tag = ([2]Tag{ .var_simple, .pub_var_simple })[@boolToInt(toplevel)] },
799780 .data = .{
800 .name = checked_name,
781 .name = name,
801782 .init = init_node,
802783 },
803784 };
804 return Node.initPayload(&payload.base);
785 const node = Node.initPayload(&payload.base);
786
787 if (toplevel) {
788 try addTopLevelDecl(c, name, node);
789 } else {
790 try scope.appendNode(node);
791 }
805792}
806793
807fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Node {
794fn transRecordDecl(c: *Context, scope: *Scope, record_decl: *const clang.RecordDecl) Error!void {
808795 if (c.decl_table.get(@ptrToInt(record_decl.getCanonicalDecl()))) |name|
809 return try Tag.identifier.create(c.arena, name); // Avoid processing this decl twice
796 return; // Avoid processing this decl twice
810797 const record_loc = record_decl.getLocation();
798 const toplevel = scope.id == .root;
799 const bs: *Scope.Block = if (!toplevel) try scope.findBlockScope(c) else undefined;
811800
812801 var bare_name = try c.str(@ptrCast(*const clang.NamedDecl, record_decl).getName_bytes_begin());
813802 var is_unnamed = false;
......@@ -826,14 +815,15 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod
826815 } else if (record_decl.isStruct()) {
827816 container_kind_name = "struct";
828817 } else {
829 try warn(c, &c.global_scope.base, record_loc, "record {s} is not a struct or union", .{bare_name});
830 return null;
818 try c.decl_table.putNoClobber(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), bare_name);
819 return failDecl(c, record_loc, bare_name, "record {s} is not a struct or union", .{bare_name});
831820 }
832821
833 const name = try std.fmt.allocPrint(c.arena, "{s}_{s}", .{ container_kind_name, bare_name });
834 _ = try c.decl_table.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), name);
822 var name: []const u8 = try std.fmt.allocPrint(c.arena, "{s}_{s}", .{ container_kind_name, bare_name });
823 if (!toplevel) name = try bs.makeMangledName(c, name);
824 try c.decl_table.putNoClobber(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), name);
835825
836 const is_pub = !is_unnamed;
826 const is_pub = toplevel and !is_unnamed;
837827 const init_node = blk: {
838828 const record_def = record_decl.getDefinition() orelse {
839829 _ = try c.opaque_demotes.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), {});
......@@ -854,13 +844,13 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod
854844
855845 if (field_decl.isBitField()) {
856846 _ = try c.opaque_demotes.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), {});
857 try warn(c, &c.global_scope.base, field_loc, "{s} demoted to opaque type - has bitfield", .{container_kind_name});
847 try warn(c, scope, field_loc, "{s} demoted to opaque type - has bitfield", .{container_kind_name});
858848 break :blk Tag.opaque_literal.init();
859849 }
860850
861851 if (qualTypeCanon(field_qt).isIncompleteOrZeroLengthArrayType(c.clang_context)) {
862852 _ = try c.opaque_demotes.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), {});
863 try warn(c, &c.global_scope.base, field_loc, "{s} demoted to opaque type - has variable length array", .{container_kind_name});
853 try warn(c, scope, field_loc, "{s} demoted to opaque type - has variable length array", .{container_kind_name});
864854 break :blk Tag.opaque_literal.init();
865855 }
866856
......@@ -872,10 +862,10 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod
872862 unnamed_field_count += 1;
873863 is_anon = true;
874864 }
875 const field_type = transQualType(c, field_qt, field_loc) catch |err| switch (err) {
865 const field_type = transQualType(c, scope, field_qt, field_loc) catch |err| switch (err) {
876866 error.UnsupportedType => {
877867 _ = try c.opaque_demotes.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), {});
878 try warn(c, &c.global_scope.base, record_loc, "{s} demoted to opaque type - unable to translate type of field {s}", .{ container_kind_name, field_name });
868 try warn(c, scope, record_loc, "{s} demoted to opaque type - unable to translate type of field {s}", .{ container_kind_name, field_name });
879869 break :blk Tag.opaque_literal.init();
880870 },
881871 else => |e| return e,
......@@ -891,7 +881,7 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod
891881 };
892882
893883 if (is_anon) {
894 _ = try c.decl_table.put(c.gpa, @ptrToInt(field_decl.getCanonicalDecl()), field_name);
884 try c.decl_table.putNoClobber(c.gpa, @ptrToInt(field_decl.getCanonicalDecl()), field_name);
895885 }
896886
897887 try fields.append(.{
......@@ -921,16 +911,21 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod
921911 },
922912 };
923913
924 try addTopLevelDecl(c, name, Node.initPayload(&payload.base));
925 if (!is_unnamed)
926 try c.alias_list.append(.{ .alias = bare_name, .name = name });
927 return try Tag.identifier.create(c.arena, name);
914 if (toplevel) {
915 try addTopLevelDecl(c, name, Node.initPayload(&payload.base));
916 if (!is_unnamed)
917 try c.alias_list.append(.{ .alias = bare_name, .name = name });
918 } else {
919 try scope.appendNode(Node.initPayload(&payload.base));
920 }
928921}
929922
930fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node {
923fn transEnumDecl(c: *Context, scope: *Scope, enum_decl: *const clang.EnumDecl) Error!void {
931924 if (c.decl_table.get(@ptrToInt(enum_decl.getCanonicalDecl()))) |name|
932 return try Tag.identifier.create(c.arena, name); // Avoid processing this decl twice
925 return; // Avoid processing this decl twice
933926 const enum_loc = enum_decl.getLocation();
927 const toplevel = scope.id == .root;
928 const bs: *Scope.Block = if (!toplevel) try scope.findBlockScope(c) else undefined;
934929
935930 var bare_name = try c.str(@ptrCast(*const clang.NamedDecl, enum_decl).getName_bytes_begin());
936931 var is_unnamed = false;
......@@ -939,10 +934,13 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node {
939934 is_unnamed = true;
940935 }
941936
942 const name = try std.fmt.allocPrint(c.arena, "enum_{s}", .{bare_name});
943 _ = try c.decl_table.put(c.gpa, @ptrToInt(enum_decl.getCanonicalDecl()), name);
937 var name: []const u8 = try std.fmt.allocPrint(c.arena, "enum_{s}", .{bare_name});
938 if (!toplevel) _ = try bs.makeMangledName(c, name);
939 try c.decl_table.putNoClobber(c.gpa, @ptrToInt(enum_decl.getCanonicalDecl()), name);
944940
945 const is_pub = !is_unnamed;
941 const is_pub = toplevel and !is_unnamed;
942 var redecls = std.ArrayList(Tag.enum_redecl.Data()).init(c.gpa);
943 defer redecls.deinit();
946944
947945 const init_node = if (enum_decl.getDefinition()) |enum_def| blk: {
948946 var pure_enum = true;
......@@ -968,10 +966,9 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node {
968966 const init_arg_expr = if (int_type.ptr != null and
969967 !isCBuiltinType(int_type, .UInt) and
970968 !isCBuiltinType(int_type, .Int))
971 transQualType(c, int_type, enum_loc) catch |err| switch (err) {
969 transQualType(c, scope, int_type, enum_loc) catch |err| switch (err) {
972970 error.UnsupportedType => {
973 try failDecl(c, enum_loc, name, "unable to translate enum tag type", .{});
974 return null;
971 return failDecl(c, enum_loc, name, "unable to translate enum tag type", .{});
975972 },
976973 else => |e| return e,
977974 }
......@@ -1001,11 +998,11 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node {
1001998
1002999 // In C each enum value is in the global namespace. So we put them there too.
10031000 // At this point we can rely on the enum emitting successfully.
1004 try addTopLevelDecl(c, field_name, try Tag.enum_redecl.create(c.arena, .{
1001 try redecls.append(.{
10051002 .enum_val_name = enum_val_name,
10061003 .field_name = field_name,
10071004 .enum_name = name,
1008 }));
1005 });
10091006 }
10101007
10111008 break :blk try Tag.@"enum".create(c.arena, .{
......@@ -1026,10 +1023,25 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node {
10261023 },
10271024 };
10281025
1029 try addTopLevelDecl(c, name, Node.initPayload(&payload.base));
1030 if (!is_unnamed)
1031 try c.alias_list.append(.{ .alias = bare_name, .name = name });
1032 return try Tag.identifier.create(c.arena, name);
1026 if (toplevel) {
1027 try addTopLevelDecl(c, name, Node.initPayload(&payload.base));
1028 if (!is_unnamed)
1029 try c.alias_list.append(.{ .alias = bare_name, .name = name });
1030 } else {
1031 try scope.appendNode(Node.initPayload(&payload.base));
1032 }
1033
1034 for (redecls.items) |redecl| {
1035 if (toplevel) {
1036 try addTopLevelDecl(c, redecl.field_name, try Tag.pub_enum_redecl.create(c.arena, redecl));
1037 } else {
1038 try scope.appendNode(try Tag.enum_redecl.create(c.arena, .{
1039 .enum_val_name = try bs.makeMangledName(c, redecl.enum_val_name),
1040 .field_name = redecl.field_name,
1041 .enum_name = redecl.enum_name,
1042 }));
1043 }
1044 }
10331045}
10341046
10351047const ResultUsed = enum {
......@@ -1251,6 +1263,7 @@ fn transCompoundStmtInline(
12511263 const end_it = stmt.body_end();
12521264 while (it != end_it) : (it += 1) {
12531265 const result = try transStmt(c, parent_scope, it[0], .unused);
1266 if (result.tag() == .declaration) continue;
12541267 try block.statements.append(result);
12551268 }
12561269}
......@@ -1285,7 +1298,7 @@ fn transDeclStmtOne(
12851298 scope: *Scope,
12861299 decl: *const clang.Decl,
12871300 block_scope: *Scope.Block,
1288) TransError!Node {
1301) TransError!void {
12891302 switch (decl.getKind()) {
12901303 .Var => {
12911304 const var_decl = @ptrCast(*const clang.VarDecl, decl);
......@@ -1299,8 +1312,7 @@ fn transDeclStmtOne(
12991312 .Extern, .Static => {
13001313 // This is actually a global variable, put it in the global scope and reference it.
13011314 // `_ = mangled_name;`
1302 try visitVarDecl(c, var_decl, mangled_name);
1303 return try maybeSuppressResult(c, scope, .unused, try Tag.identifier.create(c.arena, mangled_name));
1315 return visitVarDecl(c, var_decl, mangled_name);
13041316 },
13051317 else => {},
13061318 }
......@@ -1308,7 +1320,7 @@ fn transDeclStmtOne(
13081320 const is_const = qual_type.isConstQualified();
13091321
13101322 const loc = decl.getLocation();
1311 const type_node = try transQualTypeMaybeInitialized(c, qual_type, decl_init, loc);
1323 const type_node = try transQualTypeMaybeInitialized(c, scope, qual_type, decl_init, loc);
13121324
13131325 var init_node = if (decl_init) |expr|
13141326 if (expr.getStmtClass() == .StringLiteralClass)
......@@ -1320,7 +1332,7 @@ fn transDeclStmtOne(
13201332 if (!qualTypeIsBoolean(qual_type) and isBoolRes(init_node)) {
13211333 init_node = try Tag.bool_to_int.create(c.arena, init_node);
13221334 }
1323 return Tag.var_decl.create(c.arena, .{
1335 const node = try Tag.var_decl.create(c.arena, .{
13241336 .is_pub = false,
13251337 .is_const = is_const,
13261338 .is_extern = false,
......@@ -1332,18 +1344,16 @@ fn transDeclStmtOne(
13321344 .type = type_node,
13331345 .init = init_node,
13341346 });
1347 try block_scope.statements.append(node);
13351348 },
13361349 .Typedef => {
1337 const typedef_decl = @ptrCast(*const clang.TypedefNameDecl, decl);
1338 const name = try c.str(@ptrCast(*const clang.NamedDecl, typedef_decl).getName_bytes_begin());
1339
1340 const underlying_qual = typedef_decl.getUnderlyingType();
1341 const underlying_type = underlying_qual.getTypePtr();
1342
1343 const mangled_name = try block_scope.makeMangledName(c, name);
1344 const node = (try transCreateNodeTypedef(c, typedef_decl, false, mangled_name)) orelse
1345 return error.UnsupportedTranslation;
1346 return node;
1350 try transTypeDef(c, scope, @ptrCast(*const clang.TypedefNameDecl, decl));
1351 },
1352 .Record => {
1353 try transRecordDecl(c, scope, @ptrCast(*const clang.RecordDecl, decl));
1354 },
1355 .Enum => {
1356 try transEnumDecl(c, scope, @ptrCast(*const clang.EnumDecl, decl));
13471357 },
13481358 else => |kind| return fail(
13491359 c,
......@@ -1356,21 +1366,14 @@ fn transDeclStmtOne(
13561366}
13571367
13581368fn transDeclStmt(c: *Context, scope: *Scope, stmt: *const clang.DeclStmt) TransError!Node {
1359 const block_scope = scope.findBlockScope(c) catch unreachable;
1369 const block_scope = try scope.findBlockScope(c);
13601370
13611371 var it = stmt.decl_begin();
13621372 const end_it = stmt.decl_end();
1363 assert(it != end_it);
1364 while (true) : (it += 1) {
1365 const node = try transDeclStmtOne(c, scope, it[0], block_scope);
1366
1367 if (it + 1 == end_it) {
1368 return node;
1369 } else {
1370 try block_scope.statements.append(node);
1371 }
1373 while (it != end_it) : (it += 1) {
1374 try transDeclStmtOne(c, scope, it[0], block_scope);
13721375 }
1373 unreachable;
1376 return Tag.declaration.init();
13741377}
13751378
13761379fn transDeclRefExpr(
......@@ -1619,7 +1622,7 @@ fn transIntegerLiteral(
16191622
16201623 // @as(T, x)
16211624 const expr_base = @ptrCast(*const clang.Expr, expr);
1622 const ty_node = try transQualType(c, expr_base.getType(), expr_base.getBeginLoc());
1625 const ty_node = try transQualType(c, scope, expr_base.getType(), expr_base.getBeginLoc());
16231626 const rhs = try transCreateNodeAPInt(c, eval_result.Val.getInt());
16241627 const as = try Tag.as.create(c.arena, .{ .lhs = ty_node, .rhs = rhs });
16251628 return maybeSuppressResult(c, scope, result_used, as);
......@@ -1697,7 +1700,7 @@ fn transStringLiteralAsArray(
16971700 const ty = expr_base.getType().getTypePtr();
16981701 const const_arr_ty = @ptrCast(*const clang.ConstantArrayType, ty);
16991702
1700 const elem_type = try transQualType(c, const_arr_ty.getElementType(), expr_base.getBeginLoc());
1703 const elem_type = try transQualType(c, scope, const_arr_ty.getElementType(), expr_base.getBeginLoc());
17011704 const arr_type = try Tag.array_type.create(c.arena, .{ .len = array_size, .elem_type = elem_type });
17021705 const init_list = try c.arena.alloc(Node, array_size);
17031706
......@@ -1744,9 +1747,9 @@ fn transCCast(
17441747 if (qualTypeCanon(dst_type).isVoidType()) return expr;
17451748 if (dst_type.eq(src_type)) return expr;
17461749 if (qualTypeIsPtr(dst_type) and qualTypeIsPtr(src_type))
1747 return transCPtrCast(c, loc, dst_type, src_type, expr);
1750 return transCPtrCast(c, scope, loc, dst_type, src_type, expr);
17481751
1749 const dst_node = try transQualType(c, dst_type, loc);
1752 const dst_node = try transQualType(c, scope, dst_type, loc);
17501753 if (cIsInteger(dst_type) and (cIsInteger(src_type) or cIsEnum(src_type))) {
17511754 // 1. If src_type is an enum, determine the underlying signed int type
17521755 // 2. Extend or truncate without changing signed-ness.
......@@ -1903,7 +1906,7 @@ fn transInitListExprRecord(
19031906 const record_def = record_decl.getDefinition() orelse
19041907 unreachable;
19051908
1906 const ty_node = try transType(c, ty, loc);
1909 const ty_node = try transType(c, scope, ty, loc);
19071910 const init_count = expr.getNumInits();
19081911 var field_inits = std.ArrayList(ast.Payload.ContainerInit.Initializer).init(c.gpa);
19091912 defer field_inits.deinit();
......@@ -1952,7 +1955,7 @@ fn transInitListExprArray(
19521955) TransError!Node {
19531956 const arr_type = ty.getAsArrayTypeUnsafe();
19541957 const child_qt = arr_type.getElementType();
1955 const child_type = try transQualType(c, child_qt, loc);
1958 const child_type = try transQualType(c, scope, child_qt, loc);
19561959 const init_count = expr.getNumInits();
19571960 assert(@ptrCast(*const clang.Type, arr_type).isConstantArrayType());
19581961 const const_arr_ty = @ptrCast(*const clang.ConstantArrayType, arr_type);
......@@ -2217,7 +2220,7 @@ fn transForLoop(
22172220 block_scope = try Scope.Block.init(c, scope, false);
22182221 loop_scope.parent = &block_scope.?.base;
22192222 const init_node = try transStmt(c, &block_scope.?.base, init, .unused);
2220 try block_scope.?.statements.append(init_node);
2223 if (init_node.tag() != .declaration) try block_scope.?.statements.append(init_node);
22212224 }
22222225 var cond_scope = Scope.Condition{
22232226 .base = .{
......@@ -2328,7 +2331,7 @@ fn transCase(
23282331 scope: *Scope,
23292332 stmt: *const clang.CaseStmt,
23302333) TransError!Node {
2331 const block_scope = scope.findBlockScope(c) catch unreachable;
2334 const block_scope = try scope.findBlockScope(c);
23322335 const switch_scope = scope.getSwitch();
23332336 const label = try block_scope.makeMangledName(c, "case");
23342337
......@@ -2366,7 +2369,7 @@ fn transDefault(
23662369 scope: *Scope,
23672370 stmt: *const clang.DefaultStmt,
23682371) TransError!Node {
2369 const block_scope = scope.findBlockScope(c) catch unreachable;
2372 const block_scope = try scope.findBlockScope(c);
23702373 const switch_scope = scope.getSwitch();
23712374 switch_scope.default_label = try block_scope.makeMangledName(c, "default");
23722375
......@@ -2400,7 +2403,7 @@ fn transConstantExpr(c: *Context, scope: *Scope, expr: *const clang.Expr, used:
24002403 // @as(T, x)
24012404 const expr_base = @ptrCast(*const clang.Expr, expr);
24022405 const as_node = try Tag.as.create(c.arena, .{
2403 .lhs = try transQualType(c, expr_base.getType(), expr_base.getBeginLoc()),
2406 .lhs = try transQualType(c, scope, expr_base.getType(), expr_base.getBeginLoc()),
24042407 .rhs = try transCreateNodeAPInt(c, result.Val.getInt()),
24052408 });
24062409 return maybeSuppressResult(c, scope, used, as_node);
......@@ -2446,7 +2449,7 @@ fn transCharLiteral(
24462449 // @as(T, x)
24472450 const expr_base = @ptrCast(*const clang.Expr, stmt);
24482451 const as_node = try Tag.as.create(c.arena, .{
2449 .lhs = try transQualType(c, expr_base.getType(), expr_base.getBeginLoc()),
2452 .lhs = try transQualType(c, scope, expr_base.getType(), expr_base.getBeginLoc()),
24502453 .rhs = int_lit_node,
24512454 });
24522455 return maybeSuppressResult(c, scope, result_used, as_node);
......@@ -2464,6 +2467,7 @@ fn transStmtExpr(c: *Context, scope: *Scope, stmt: *const clang.StmtExpr, used:
24642467 const end_it = comp.body_end();
24652468 while (it != end_it - 1) : (it += 1) {
24662469 const result = try transStmt(c, &block_scope.base, it[0], .unused);
2470 if (result.tag() == .declaration) continue;
24672471 try block_scope.statements.append(result);
24682472 }
24692473 const break_node = try Tag.break_val.create(c.arena, .{
......@@ -2657,7 +2661,7 @@ fn transUnaryExprOrTypeTraitExpr(
26572661 result_used: ResultUsed,
26582662) TransError!Node {
26592663 const loc = stmt.getBeginLoc();
2660 const type_node = try transQualType(c, stmt.getTypeOfArgument(), loc);
2664 const type_node = try transQualType(c, scope, stmt.getTypeOfArgument(), loc);
26612665
26622666 const kind = stmt.getKind();
26632667 switch (kind) {
......@@ -2917,9 +2921,9 @@ fn transCreateCompoundAssign(
29172921 if (is_shift or requires_int_cast) {
29182922 // @intCast(rhs)
29192923 const cast_to_type = if (is_shift)
2920 try qualTypeToLog2IntRef(c, getExprQualType(c, rhs), loc)
2924 try qualTypeToLog2IntRef(c, scope, getExprQualType(c, rhs), loc)
29212925 else
2922 try transQualType(c, getExprQualType(c, lhs), loc);
2926 try transQualType(c, scope, getExprQualType(c, lhs), loc);
29232927
29242928 rhs_node = try Tag.int_cast.create(c.arena, .{ .lhs = cast_to_type, .rhs = rhs_node });
29252929 }
......@@ -2960,9 +2964,9 @@ fn transCreateCompoundAssign(
29602964 if (is_shift or requires_int_cast) {
29612965 // @intCast(rhs)
29622966 const cast_to_type = if (is_shift)
2963 try qualTypeToLog2IntRef(c, getExprQualType(c, rhs), loc)
2967 try qualTypeToLog2IntRef(c, scope, getExprQualType(c, rhs), loc)
29642968 else
2965 try transQualType(c, getExprQualType(c, lhs), loc);
2969 try transQualType(c, scope, getExprQualType(c, lhs), loc);
29662970
29672971 rhs_node = try Tag.int_cast.create(c.arena, .{ .lhs = cast_to_type, .rhs = rhs_node });
29682972 }
......@@ -2981,6 +2985,7 @@ fn transCreateCompoundAssign(
29812985
29822986fn transCPtrCast(
29832987 c: *Context,
2988 scope: *Scope,
29842989 loc: clang.SourceLocation,
29852990 dst_type: clang.QualType,
29862991 src_type: clang.QualType,
......@@ -2990,7 +2995,7 @@ fn transCPtrCast(
29902995 const child_type = ty.getPointeeType();
29912996 const src_ty = src_type.getTypePtr();
29922997 const src_child_type = src_ty.getPointeeType();
2993 const dst_type_node = try transType(c, ty, loc);
2998 const dst_type_node = try transType(c, scope, ty, loc);
29942999
29953000 if ((src_child_type.isConstQualified() and
29963001 !child_type.isConstQualified()) or
......@@ -3011,7 +3016,7 @@ fn transCPtrCast(
30113016 // For opaque types a ptrCast is enough
30123017 expr
30133018 else blk: {
3014 const child_type_node = try transQualType(c, child_type, loc);
3019 const child_type_node = try transQualType(c, scope, child_type, loc);
30153020 const alignof = try Tag.alignof.create(c.arena, child_type_node);
30163021 const align_cast = try Tag.align_cast.create(c.arena, .{ .lhs = alignof, .rhs = expr });
30173022 break :blk align_cast;
......@@ -3160,6 +3165,7 @@ fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: Node) !void {
31603165/// by the size of the initializer
31613166fn transQualTypeInitialized(
31623167 c: *Context,
3168 scope: *Scope,
31633169 qt: clang.QualType,
31643170 decl_init: *const clang.Expr,
31653171 source_loc: clang.SourceLocation,
......@@ -3167,7 +3173,7 @@ fn transQualTypeInitialized(
31673173 const ty = qt.getTypePtr();
31683174 if (ty.getTypeClass() == .IncompleteArray) {
31693175 const incomplete_array_ty = @ptrCast(*const clang.IncompleteArrayType, ty);
3170 const elem_ty = try transType(c, incomplete_array_ty.getElementType().getTypePtr(), source_loc);
3176 const elem_ty = try transType(c, scope, incomplete_array_ty.getElementType().getTypePtr(), source_loc);
31713177
31723178 switch (decl_init.getStmtClass()) {
31733179 .StringLiteralClass => {
......@@ -3184,11 +3190,11 @@ fn transQualTypeInitialized(
31843190 else => {},
31853191 }
31863192 }
3187 return transQualType(c, qt, source_loc);
3193 return transQualType(c, scope, qt, source_loc);
31883194}
31893195
3190fn transQualType(c: *Context, qt: clang.QualType, source_loc: clang.SourceLocation) TypeError!Node {
3191 return transType(c, qt.getTypePtr(), source_loc);
3196fn transQualType(c: *Context, scope: *Scope, qt: clang.QualType, source_loc: clang.SourceLocation) TypeError!Node {
3197 return transType(c, scope, qt.getTypePtr(), source_loc);
31923198}
31933199
31943200/// Produces a Zig AST node by translating a Clang QualType, respecting the width, but modifying the signed-ness.
......@@ -3273,7 +3279,7 @@ fn qualTypeIntBitWidth(c: *Context, qt: clang.QualType) !u32 {
32733279 }
32743280}
32753281
3276fn qualTypeToLog2IntRef(c: *Context, qt: clang.QualType, source_loc: clang.SourceLocation) !Node {
3282fn qualTypeToLog2IntRef(c: *Context, scope: *Scope, qt: clang.QualType, source_loc: clang.SourceLocation) !Node {
32773283 const int_bit_width = try qualTypeIntBitWidth(c, qt);
32783284
32793285 if (int_bit_width != 0) {
......@@ -3282,7 +3288,7 @@ fn qualTypeToLog2IntRef(c: *Context, qt: clang.QualType, source_loc: clang.Sourc
32823288 return Tag.log2_int_type.create(c.arena, cast_bit_width);
32833289 }
32843290
3285 const zig_type = try transQualType(c, qt, source_loc);
3291 const zig_type = try transQualType(c, scope, qt, source_loc);
32863292 return Tag.std_math_Log2Int.create(c.arena, zig_type);
32873293}
32883294
......@@ -3641,14 +3647,14 @@ fn transCreateNodeShiftOp(
36413647
36423648 const lhs = try transExpr(c, scope, lhs_expr, .used);
36433649
3644 const rhs_type = try qualTypeToLog2IntRef(c, stmt.getType(), rhs_location);
3650 const rhs_type = try qualTypeToLog2IntRef(c, scope, stmt.getType(), rhs_location);
36453651 const rhs = try transExprCoercing(c, scope, rhs_expr, .used);
36463652 const rhs_casted = try Tag.int_cast.create(c.arena, .{ .lhs = rhs_type, .rhs = rhs });
36473653
36483654 return transCreateNodeInfixOp(c, scope, op, lhs, rhs_casted, used);
36493655}
36503656
3651fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocation) TypeError!Node {
3657fn transType(c: *Context, scope: *Scope, ty: *const clang.Type, source_loc: clang.SourceLocation) TypeError!Node {
36523658 switch (ty.getTypeClass()) {
36533659 .Builtin => {
36543660 const builtin_ty = @ptrCast(*const clang.BuiltinType, ty);
......@@ -3687,16 +3693,16 @@ fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocatio
36873693 },
36883694 .Paren => {
36893695 const paren_ty = @ptrCast(*const clang.ParenType, ty);
3690 return transQualType(c, paren_ty.getInnerType(), source_loc);
3696 return transQualType(c, scope, paren_ty.getInnerType(), source_loc);
36913697 },
36923698 .Pointer => {
36933699 const child_qt = ty.getPointeeType();
36943700 if (qualTypeChildIsFnProto(child_qt)) {
3695 return Tag.optional_type.create(c.arena, try transQualType(c, child_qt, source_loc));
3701 return Tag.optional_type.create(c.arena, try transQualType(c, scope, child_qt, source_loc));
36963702 }
36973703 const is_const = child_qt.isConstQualified();
36983704 const is_volatile = child_qt.isVolatileQualified();
3699 const elem_type = try transQualType(c, child_qt, source_loc);
3705 const elem_type = try transQualType(c, scope, child_qt, source_loc);
37003706 if (typeIsOpaque(c, child_qt.getTypePtr(), source_loc) or qualTypeWasDemotedToOpaque(c, child_qt)) {
37013707 const ptr = try Tag.single_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type });
37023708 return Tag.optional_type.create(c.arena, ptr);
......@@ -3709,7 +3715,7 @@ fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocatio
37093715
37103716 const size_ap_int = const_arr_ty.getSize();
37113717 const size = size_ap_int.getLimitedValue(math.maxInt(usize));
3712 const elem_type = try transType(c, const_arr_ty.getElementType().getTypePtr(), source_loc);
3718 const elem_type = try transType(c, scope, const_arr_ty.getElementType().getTypePtr(), source_loc);
37133719
37143720 return Tag.array_type.create(c.arena, .{ .len = size, .elem_type = elem_type });
37153721 },
......@@ -3719,7 +3725,7 @@ fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocatio
37193725 const child_qt = incomplete_array_ty.getElementType();
37203726 const is_const = child_qt.isConstQualified();
37213727 const is_volatile = child_qt.isVolatileQualified();
3722 const elem_type = try transQualType(c, child_qt, source_loc);
3728 const elem_type = try transQualType(c, scope, child_qt, source_loc);
37233729
37243730 return Tag.c_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type });
37253731 },
......@@ -3727,38 +3733,41 @@ fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocatio
37273733 const typedef_ty = @ptrCast(*const clang.TypedefType, ty);
37283734
37293735 const typedef_decl = typedef_ty.getDecl();
3730 return (try transTypeDef(c, typedef_decl, false)) orelse
3731 fail(c, error.UnsupportedType, source_loc, "unable to translate typedef declaration", .{});
3736 try transTypeDef(c, scope, typedef_decl);
3737 const name = c.decl_table.get(@ptrToInt(typedef_decl.getCanonicalDecl())).?;
3738 return Tag.identifier.create(c.arena, name);
37323739 },
37333740 .Record => {
37343741 const record_ty = @ptrCast(*const clang.RecordType, ty);
37353742
37363743 const record_decl = record_ty.getDecl();
3737 return (try transRecordDecl(c, record_decl)) orelse
3738 fail(c, error.UnsupportedType, source_loc, "unable to resolve record declaration", .{});
3744 try transRecordDecl(c, scope, record_decl);
3745 const name = c.decl_table.get(@ptrToInt(record_decl.getCanonicalDecl())).?;
3746 return Tag.identifier.create(c.arena, name);
37393747 },
37403748 .Enum => {
37413749 const enum_ty = @ptrCast(*const clang.EnumType, ty);
37423750
37433751 const enum_decl = enum_ty.getDecl();
3744 return (try transEnumDecl(c, enum_decl)) orelse
3745 fail(c, error.UnsupportedType, source_loc, "unable to translate enum declaration", .{});
3752 try transEnumDecl(c, scope, enum_decl);
3753 const name = c.decl_table.get(@ptrToInt(enum_decl.getCanonicalDecl())).?;
3754 return Tag.identifier.create(c.arena, name);
37463755 },
37473756 .Elaborated => {
37483757 const elaborated_ty = @ptrCast(*const clang.ElaboratedType, ty);
3749 return transQualType(c, elaborated_ty.getNamedType(), source_loc);
3758 return transQualType(c, scope, elaborated_ty.getNamedType(), source_loc);
37503759 },
37513760 .Decayed => {
37523761 const decayed_ty = @ptrCast(*const clang.DecayedType, ty);
3753 return transQualType(c, decayed_ty.getDecayedType(), source_loc);
3762 return transQualType(c, scope, decayed_ty.getDecayedType(), source_loc);
37543763 },
37553764 .Attributed => {
37563765 const attributed_ty = @ptrCast(*const clang.AttributedType, ty);
3757 return transQualType(c, attributed_ty.getEquivalentType(), source_loc);
3766 return transQualType(c, scope, attributed_ty.getEquivalentType(), source_loc);
37583767 },
37593768 .MacroQualified => {
37603769 const macroqualified_ty = @ptrCast(*const clang.MacroQualifiedType, ty);
3761 return transQualType(c, macroqualified_ty.getModifiedType(), source_loc);
3770 return transQualType(c, scope, macroqualified_ty.getModifiedType(), source_loc);
37623771 },
37633772 else => {
37643773 const type_name = c.str(ty.getTypeClassName());
......@@ -3890,6 +3899,7 @@ fn finishTransFnProto(
38903899) !*ast.Payload.Func {
38913900 const is_export = if (fn_decl_context) |ctx| ctx.is_export else false;
38923901 const is_extern = if (fn_decl_context) |ctx| !ctx.has_body else false;
3902 const scope = &c.global_scope.base;
38933903
38943904 // TODO check for always_inline attribute
38953905 // TODO check for align attribute
......@@ -3914,7 +3924,7 @@ fn finishTransFnProto(
39143924
39153925 break :blk param_name;
39163926 } else null;
3917 const type_node = try transQualType(c, param_qt, source_loc);
3927 const type_node = try transQualType(c, scope, param_qt, source_loc);
39183928
39193929 fn_params.addOneAssumeCapacity().* = .{
39203930 .is_noalias = is_noalias,
......@@ -3955,9 +3965,9 @@ fn finishTransFnProto(
39553965 // convert primitive c_void to actual void (only for return type)
39563966 break :blk Tag.void_type.init();
39573967 } else {
3958 break :blk transQualType(c, return_qt, source_loc) catch |err| switch (err) {
3968 break :blk transQualType(c, scope, return_qt, source_loc) catch |err| switch (err) {
39593969 error.UnsupportedType => {
3960 try warn(c, &c.global_scope.base, source_loc, "unsupported function proto return type", .{});
3970 try warn(c, scope, source_loc, "unsupported function proto return type", .{});
39613971 return err;
39623972 },
39633973 error.OutOfMemory => |e| return e,
src/translate_c/ast.zig+11-4
......@@ -14,6 +14,8 @@ pub const Node = extern union {
1414 ptr_otherwise: *Payload,
1515
1616 pub const Tag = enum {
17 /// Declarations add themselves to the correct scopes and should not be emitted as this tag.
18 declaration,
1719 null_literal,
1820 undefined_literal,
1921 /// opaque {}
......@@ -186,6 +188,7 @@ pub const Node = extern union {
186188 /// pub const name = init;
187189 pub_var_simple,
188190 /// pub const enum_field_name = @enumToInt(enum_name.field_name);
191 pub_enum_redecl,
189192 enum_redecl,
190193
191194 /// pub inline fn name(params) return_type body
......@@ -201,6 +204,7 @@ pub const Node = extern union {
201204
202205 pub fn Type(comptime t: Tag) type {
203206 return switch (t) {
207 .declaration,
204208 .null_literal,
205209 .undefined_literal,
206210 .opaque_literal,
......@@ -325,7 +329,7 @@ pub const Node = extern union {
325329 .arg_redecl, .alias, .fail_decl => Payload.ArgRedecl,
326330 .log2_int_type => Payload.Log2IntType,
327331 .var_simple, .pub_var_simple => Payload.SimpleVarDecl,
328 .enum_redecl => Payload.EnumRedecl,
332 .pub_enum_redecl, .enum_redecl => Payload.EnumRedecl,
329333 .array_filler => Payload.ArrayFiller,
330334 .pub_inline_fn => Payload.PubInlineFn,
331335 .field_access => Payload.FieldAccess,
......@@ -742,6 +746,7 @@ fn renderNodes(c: *Context, nodes: []const Node) Allocator.Error!NodeSubRange {
742746
743747fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
744748 switch (node.tag()) {
749 .declaration => unreachable,
745750 .warning => {
746751 const payload = node.castTag(.warning).?.data;
747752 try c.buf.appendSlice(payload);
......@@ -1585,9 +1590,9 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
15851590 },
15861591 });
15871592 },
1588 .enum_redecl => {
1589 const payload = node.castTag(.enum_redecl).?.data;
1590 _ = try c.addToken(.keyword_pub, "pub");
1593 .pub_enum_redecl, .enum_redecl => {
1594 const payload = @fieldParentPtr(Payload.EnumRedecl, "base", node.ptr_otherwise).data;
1595 if (node.tag() == .pub_enum_redecl) _ = try c.addToken(.keyword_pub, "pub");
15911596 const const_tok = try c.addToken(.keyword_const, "const");
15921597 _ = try c.addIdentifier(payload.enum_val_name);
15931598 _ = try c.addToken(.equal, "=");
......@@ -1878,6 +1883,7 @@ fn addSemicolonIfNotBlock(c: *Context, node: Node) !void {
18781883
18791884fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
18801885 switch (node.tag()) {
1886 .declaration => unreachable,
18811887 .null_literal,
18821888 .undefined_literal,
18831889 .true_literal,
......@@ -1991,6 +1997,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
19911997 .alias,
19921998 .var_simple,
19931999 .pub_var_simple,
2000 .pub_enum_redecl,
19942001 .enum_redecl,
19952002 .@"while",
19962003 .@"switch",
test/translate_c.zig+157-25
......@@ -3,6 +3,136 @@ const std = @import("std");
33const CrossTarget = std.zig.CrossTarget;
44
55pub fn addCases(cases: *tests.TranslateCContext) void {
6 cases.add("scoped enum",
7 \\void foo() {
8 \\ enum Foo {
9 \\ A,
10 \\ B,
11 \\ C,
12 \\ };
13 \\ enum Foo a = B;
14 \\ {
15 \\ enum Foo {
16 \\ A,
17 \\ B,
18 \\ C,
19 \\ };
20 \\ enum Foo a = B;
21 \\ }
22 \\}
23 , &[_][]const u8{
24 \\pub export fn foo() void {
25 \\ const enum_Foo = extern enum(c_int) {
26 \\ A,
27 \\ B,
28 \\ C,
29 \\ _,
30 \\ };
31 \\ const A = @enumToInt(enum_Foo.A);
32 \\ const B = @enumToInt(enum_Foo.B);
33 \\ const C = @enumToInt(enum_Foo.C);
34 \\ var a: enum_Foo = @intToEnum(enum_Foo, B);
35 \\ {
36 \\ const enum_Foo = extern enum(c_int) {
37 \\ A,
38 \\ B,
39 \\ C,
40 \\ _,
41 \\ };
42 \\ const A_2 = @enumToInt(enum_Foo.A);
43 \\ const B_3 = @enumToInt(enum_Foo.B);
44 \\ const C_4 = @enumToInt(enum_Foo.C);
45 \\ var a_5: enum_Foo = @intToEnum(enum_Foo, B_3);
46 \\ }
47 \\}
48 });
49
50 cases.add("scoped record",
51 \\void foo() {
52 \\ struct Foo {
53 \\ int A;
54 \\ int B;
55 \\ int C;
56 \\ };
57 \\ struct Foo a = {0};
58 \\ {
59 \\ struct Foo {
60 \\ int A;
61 \\ int B;
62 \\ int C;
63 \\ };
64 \\ struct Foo a = {0};
65 \\ }
66 \\}
67 , &[_][]const u8{
68 \\pub export fn foo() void {
69 \\ const struct_Foo = extern struct {
70 \\ A: c_int,
71 \\ B: c_int,
72 \\ C: c_int,
73 \\ };
74 \\ var a: struct_Foo = struct_Foo{
75 \\ .A = @as(c_int, 0),
76 \\ .B = 0,
77 \\ .C = 0,
78 \\ };
79 \\ {
80 \\ const struct_Foo_1 = extern struct {
81 \\ A: c_int,
82 \\ B: c_int,
83 \\ C: c_int,
84 \\ };
85 \\ var a_2: struct_Foo_1 = struct_Foo_1{
86 \\ .A = @as(c_int, 0),
87 \\ .B = 0,
88 \\ .C = 0,
89 \\ };
90 \\ }
91 \\}
92 });
93
94 cases.add("scoped typedef",
95 \\void foo() {
96 \\ typedef union {
97 \\ int A;
98 \\ int B;
99 \\ int C;
100 \\ } Foo;
101 \\ Foo a = {0};
102 \\ {
103 \\ typedef union {
104 \\ int A;
105 \\ int B;
106 \\ int C;
107 \\ } Foo;
108 \\ Foo a = {0};
109 \\ }
110 \\}
111 , &[_][]const u8{
112 \\pub export fn foo() void {
113 \\ const union_unnamed_1 = extern union {
114 \\ A: c_int,
115 \\ B: c_int,
116 \\ C: c_int,
117 \\ };
118 \\ const Foo = union_unnamed_1;
119 \\ var a: Foo = Foo{
120 \\ .A = @as(c_int, 0),
121 \\ };
122 \\ {
123 \\ const union_unnamed_2 = extern union {
124 \\ A: c_int,
125 \\ B: c_int,
126 \\ C: c_int,
127 \\ };
128 \\ const Foo_1 = union_unnamed_2;
129 \\ var a_2: Foo_1 = Foo_1{
130 \\ .A = @as(c_int, 0),
131 \\ };
132 \\ }
133 \\}
134 });
135
6136 cases.add("use cast param as macro fn return type",
7137 \\#define MEM_PHYSICAL_TO_K0(x) (void*)((u32)(x) + SYS_BASE_CACHED)
8138 , &[_][]const u8{
......@@ -62,7 +192,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
62192 \\pub export var bar: f32 = @import("std").mem.zeroes(f32);
63193 \\threadlocal var bar_1: c_int = 2;
64194 \\pub export fn foo() c_int {
65 \\ _ = bar_1;
66195 \\ return 0;
67196 \\}
68197 });
......@@ -579,9 +708,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
579708 \\ '2',
580709 \\ 0,
581710 \\};
582 \\pub export fn foo() void {
583 \\ _ = v2;
584 \\}
711 \\pub export fn foo() void {}
585712 });
586713
587714 cases.add("simple function definition",
......@@ -1355,11 +1482,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
13551482 \\extern enum enum_ty my_enum;
13561483 \\enum enum_ty { FOO };
13571484 , &[_][]const u8{
1358 \\pub const FOO = @enumToInt(enum_enum_ty.FOO);
13591485 \\pub const enum_enum_ty = extern enum(c_int) {
13601486 \\ FOO,
13611487 \\ _,
13621488 \\};
1489 \\pub const FOO = @enumToInt(enum_enum_ty.FOO);
13631490 \\pub extern var my_enum: enum_enum_ty;
13641491 });
13651492
......@@ -1501,48 +1628,48 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
15011628 \\ p,
15021629 \\};
15031630 , &[_][]const u8{
1504 \\pub const a = @enumToInt(enum_unnamed_1.a);
1505 \\pub const b = @enumToInt(enum_unnamed_1.b);
1506 \\pub const c = @enumToInt(enum_unnamed_1.c);
15071631 \\const enum_unnamed_1 = extern enum(c_int) {
15081632 \\ a,
15091633 \\ b,
15101634 \\ c,
15111635 \\ _,
15121636 \\};
1637 \\pub const a = @enumToInt(enum_unnamed_1.a);
1638 \\pub const b = @enumToInt(enum_unnamed_1.b);
1639 \\pub const c = @enumToInt(enum_unnamed_1.c);
15131640 \\pub const d = enum_unnamed_1;
1514 \\pub const e = @enumToInt(enum_unnamed_2.e);
1515 \\pub const f = @enumToInt(enum_unnamed_2.f);
1516 \\pub const g = @enumToInt(enum_unnamed_2.g);
15171641 \\const enum_unnamed_2 = extern enum(c_int) {
15181642 \\ e = 0,
15191643 \\ f = 4,
15201644 \\ g = 5,
15211645 \\ _,
15221646 \\};
1647 \\pub const e = @enumToInt(enum_unnamed_2.e);
1648 \\pub const f = @enumToInt(enum_unnamed_2.f);
1649 \\pub const g = @enumToInt(enum_unnamed_2.g);
15231650 \\pub export var h: enum_unnamed_2 = @intToEnum(enum_unnamed_2, e);
1524 \\pub const i = @enumToInt(enum_unnamed_3.i);
1525 \\pub const j = @enumToInt(enum_unnamed_3.j);
1526 \\pub const k = @enumToInt(enum_unnamed_3.k);
15271651 \\const enum_unnamed_3 = extern enum(c_int) {
15281652 \\ i,
15291653 \\ j,
15301654 \\ k,
15311655 \\ _,
15321656 \\};
1657 \\pub const i = @enumToInt(enum_unnamed_3.i);
1658 \\pub const j = @enumToInt(enum_unnamed_3.j);
1659 \\pub const k = @enumToInt(enum_unnamed_3.k);
15331660 \\pub const struct_Baz = extern struct {
15341661 \\ l: enum_unnamed_3,
15351662 \\ m: d,
15361663 \\};
1537 \\pub const n = @enumToInt(enum_i.n);
1538 \\pub const o = @enumToInt(enum_i.o);
1539 \\pub const p = @enumToInt(enum_i.p);
15401664 \\pub const enum_i = extern enum(c_int) {
15411665 \\ n,
15421666 \\ o,
15431667 \\ p,
15441668 \\ _,
15451669 \\};
1670 \\pub const n = @enumToInt(enum_i.n);
1671 \\pub const o = @enumToInt(enum_i.o);
1672 \\pub const p = @enumToInt(enum_i.p);
15461673 ,
15471674 \\pub const Baz = struct_Baz;
15481675 });
......@@ -1989,13 +2116,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
19892116 \\ Two,
19902117 \\};
19912118 , &[_][]const u8{
1992 \\pub const One = @enumToInt(enum_unnamed_1.One);
1993 \\pub const Two = @enumToInt(enum_unnamed_1.Two);
19942119 \\const enum_unnamed_1 = extern enum(c_int) {
19952120 \\ One,
19962121 \\ Two,
19972122 \\ _,
19982123 \\};
2124 \\pub const One = @enumToInt(enum_unnamed_1.One);
2125 \\pub const Two = @enumToInt(enum_unnamed_1.Two);
19992126 });
20002127
20012128 cases.add("c style cast",
......@@ -2093,15 +2220,15 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
20932220 \\ return ((((((((((e + f) + g) + h) + i) + j) + k) + l) + m) + o) + p);
20942221 \\}
20952222 , &[_][]const u8{
2096 \\pub const FooA = @enumToInt(enum_Foo.A);
2097 \\pub const FooB = @enumToInt(enum_Foo.B);
2098 \\pub const FooC = @enumToInt(enum_Foo.C);
20992223 \\pub const enum_Foo = extern enum(c_int) {
21002224 \\ A,
21012225 \\ B,
21022226 \\ C,
21032227 \\ _,
21042228 \\};
2229 \\pub const FooA = @enumToInt(enum_Foo.A);
2230 \\pub const FooB = @enumToInt(enum_Foo.B);
2231 \\pub const FooC = @enumToInt(enum_Foo.C);
21052232 \\pub const SomeTypedef = c_int;
21062233 \\pub export fn and_or_non_bool(arg_a: c_int, arg_b: f32, arg_c: ?*c_void) c_int {
21072234 \\ var a = arg_a;
......@@ -2147,6 +2274,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
21472274 \\ B,
21482275 \\ _,
21492276 \\};
2277 \\pub const BarA = @enumToInt(enum_Bar.A);
2278 \\pub const BarB = @enumToInt(enum_Bar.B);
21502279 \\pub extern fn func(a: [*c]struct_Foo, b: [*c][*c]enum_Bar) void;
21512280 ,
21522281 \\pub const Foo = struct_Foo;
......@@ -2413,6 +2542,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
24132542 \\ C,
24142543 \\ _,
24152544 \\};
2545 \\pub const A = @enumToInt(enum_SomeEnum.A);
2546 \\pub const B = @enumToInt(enum_SomeEnum.B);
2547 \\pub const C = @enumToInt(enum_SomeEnum.C);
24162548 \\pub export fn if_none_bool(arg_a: c_int, arg_b: f32, arg_c: ?*c_void, arg_d: enum_SomeEnum) c_int {
24172549 \\ var a = arg_a;
24182550 \\ var b = arg_b;
......@@ -2872,15 +3004,15 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
28723004 \\ Foo1,
28733005 \\};
28743006 , &[_][]const u8{
2875 \\pub const FooA = @enumToInt(enum_Foo.A);
2876 \\pub const FooB = @enumToInt(enum_Foo.B);
2877 \\pub const Foo1 = @enumToInt(enum_Foo.@"1");
28783007 \\pub const enum_Foo = extern enum(c_int) {
28793008 \\ A = 2,
28803009 \\ B = 5,
28813010 \\ @"1" = 6,
28823011 \\ _,
28833012 \\};
3013 \\pub const FooA = @enumToInt(enum_Foo.A);
3014 \\pub const FooB = @enumToInt(enum_Foo.B);
3015 \\pub const Foo1 = @enumToInt(enum_Foo.@"1");
28843016 ,
28853017 \\pub const Foo = enum_Foo;
28863018 });