authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-17 22:05:07+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-17 22:05:07+02:00
loga6960b89ed9b1a5951d08b1f7d8e215c86bb9e7e
treee684e76cdaf1a7dd154228699acda6bde4f86092
parent65531c73a909386824697bb16025c363684a3a66
signature Commit is signed but in an unrecognized format.

translate-c-2 fix container type resolution


2 files changed, 263 insertions(+), 284 deletions(-)

src-self-hosted/translate_c.zig+242-276
......@@ -371,13 +371,13 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void {
371371 return visitFnDecl(c, @ptrCast(*const ZigClangFunctionDecl, decl));
372372 },
373373 .Typedef => {
374 return resolveTypeDef(c, @ptrCast(*const ZigClangTypedefNameDecl, decl));
374 _ = try transTypeDef(c, @ptrCast(*const ZigClangTypedefNameDecl, decl));
375375 },
376376 .Enum => {
377377 _ = try transEnumDecl(c, @ptrCast(*const ZigClangEnumDecl, decl));
378378 },
379379 .Record => {
380 return resolveRecordDecl(c, @ptrCast(*const ZigClangRecordDecl, decl));
380 _ = try transRecordDecl(c, @ptrCast(*const ZigClangRecordDecl, decl));
381381 },
382382 .Var => {
383383 return visitVarDecl(c, @ptrCast(*const ZigClangVarDecl, decl));
......@@ -541,10 +541,9 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
541541 return addTopLevelDecl(c, checked_name, &node.base);
542542}
543543
544fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Error!void {
545 if (c.decl_table.contains(
546 @ptrToInt(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl)),
547 )) return; // Avoid processing this decl twice
544fn transTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Error!?*ast.Node {
545 if (c.decl_table.get(@ptrToInt(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl)))) |kv|
546 return try transCreateNodeIdentifier(c, kv.value); // Avoid processing this decl twice
548547 const rp = makeRestorePoint(c);
549548 const visib_tok = try appendToken(c, .Keyword_pub, "pub");
550549 const const_tok = try appendToken(c, .Keyword_const, "const");
......@@ -558,29 +557,40 @@ fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Err
558557 const typedef_loc = ZigClangTypedefNameDecl_getLocation(typedef_decl);
559558 node.init_node = transQualType(rp, child_qt, typedef_loc) catch |err| switch (err) {
560559 error.UnsupportedType => {
561 return failDecl(c, typedef_loc, typedef_name, "unable to resolve typedef child type", .{});
560 try failDecl(c, typedef_loc, typedef_name, "unable to resolve typedef child type", .{});
561 return null;
562562 },
563563 error.OutOfMemory => |e| return e,
564564 };
565565 node.semicolon_token = try appendToken(c, .Semicolon, ";");
566566 try addTopLevelDecl(c, typedef_name, &node.base);
567 return transCreateNodeIdentifier(c, typedef_name);
567568}
568569
569fn resolveRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!void {
570 if (c.decl_table.contains(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)))) return; // Avoid processing this decl twice
571 const rp = makeRestorePoint(c);
572
573 const bare_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, record_decl)));
570fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*ast.Node {
571 if (c.decl_table.get(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)))) |kv|
572 return try transCreateNodeIdentifier(c, kv.value); // Avoid processing this decl twice
573 const record_loc = ZigClangRecordDecl_getLocation(record_decl);
574574
575 const container_kind_name = if (ZigClangRecordDecl_isUnion(record_decl))
576 "union"
577 else if (ZigClangRecordDecl_isStruct(record_decl))
578 "struct"
579 else
580 return emitWarning(c, ZigClangRecordDecl_getLocation(record_decl), "record {} is not a struct or union", .{bare_name});
575 var bare_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, record_decl)));
576 var is_unnamed = false;
577 if (ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl) or bare_name.len == 0) {
578 bare_name = try std.fmt.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()});
579 is_unnamed = true;
580 }
581581
582 if (ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl) or bare_name.len == 0)
583 return;
582 var container_kind_name: []const u8 = undefined;
583 var container_kind: std.zig.Token.Id = undefined;
584 if (ZigClangRecordDecl_isUnion(record_decl)) {
585 container_kind_name = "union";
586 container_kind = .Keyword_union;
587 } else if (ZigClangRecordDecl_isStruct(record_decl)) {
588 container_kind_name = "struct";
589 container_kind = .Keyword_struct;
590 } else {
591 try emitWarning(c, record_loc, "record {} is not a struct or union", .{bare_name});
592 return null;
593 }
584594
585595 const name = try std.fmt.allocPrint(c.a(), "{}_{}", .{ container_kind_name, bare_name });
586596 _ = try c.decl_table.put(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)), name);
......@@ -588,16 +598,211 @@ fn resolveRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!
588598 const node = try transCreateNodeVarDecl(c, true, true, name);
589599
590600 node.eq_token = try appendToken(c, .Equal, "=");
591 node.init_node = transRecordDecl(c, record_decl) catch |err| switch (err) {
592 error.UnsupportedType => {
593 return failDecl(c, ZigClangRecordDecl_getLocation(record_decl), name, "unable to resolve record type", .{});
594 },
595 error.OutOfMemory => |e| return e,
601
602 var semicolon: ast.TokenIndex = undefined;
603 node.init_node = blk: {
604 const rp = makeRestorePoint(c);
605 const record_def = ZigClangRecordDecl_getDefinition(record_decl) orelse {
606 const opaque = try transCreateNodeOpaqueType(c);
607 semicolon = try appendToken(c, .Semicolon, ";");
608 break :blk opaque;
609 };
610
611 const extern_tok = try appendToken(c, .Keyword_extern, "extern");
612 const container_tok = try appendToken(c, container_kind, container_kind_name);
613 const lbrace_token = try appendToken(c, .LBrace, "{");
614
615 const container_node = try c.a().create(ast.Node.ContainerDecl);
616 container_node.* = .{
617 .layout_token = extern_tok,
618 .kind_token = container_tok,
619 .init_arg_expr = .None,
620 .fields_and_decls = ast.Node.ContainerDecl.DeclList.init(c.a()),
621 .lbrace_token = lbrace_token,
622 .rbrace_token = undefined,
623 };
624
625 var it = ZigClangRecordDecl_field_begin(record_def);
626 const end_it = ZigClangRecordDecl_field_end(record_def);
627 while (ZigClangRecordDecl_field_iterator_neq(it, end_it)) : (it = ZigClangRecordDecl_field_iterator_next(it)) {
628 const field_decl = ZigClangRecordDecl_field_iterator_deref(it);
629 const field_loc = ZigClangFieldDecl_getLocation(field_decl);
630
631 if (ZigClangFieldDecl_isBitField(field_decl)) {
632 const opaque = try transCreateNodeOpaqueType(c);
633 semicolon = try appendToken(c, .Semicolon, ";");
634 try emitWarning(c, field_loc, "{} demoted to opaque type - has bitfield", .{container_kind_name});
635 break :blk opaque;
636 }
637
638 const field_name = try appendIdentifier(c, try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, field_decl))));
639 _ = try appendToken(c, .Colon, ":");
640 const field_type = transQualType(rp, ZigClangFieldDecl_getType(field_decl), field_loc) catch |err| switch (err) {
641 error.UnsupportedType => {
642 try failDecl(c, record_loc, name, "unable to translate {} member type", .{container_kind_name});
643 return null;
644 },
645 else => |e| return e,
646 };
647
648 const field_node = try c.a().create(ast.Node.ContainerField);
649 field_node.* = .{
650 .doc_comments = null,
651 .comptime_token = null,
652 .name_token = field_name,
653 .type_expr = field_type,
654 .value_expr = null,
655 .align_expr = null,
656 };
657
658 try container_node.fields_and_decls.push(&field_node.base);
659 _ = try appendToken(c, .Comma, ",");
660 }
661 container_node.rbrace_token = try appendToken(c, .RBrace, "}");
662 semicolon = try appendToken(c, .Semicolon, ";");
663 break :blk &container_node.base;
596664 };
665 node.semicolon_token = semicolon;
666
667 try addTopLevelDecl(c, name, &node.base);
668 if (!is_unnamed)
669 try c.alias_list.push(.{ .alias = bare_name, .name = name });
670 return transCreateNodeIdentifier(c, name);
671}
672
673fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.Node {
674 if (c.decl_table.get(@ptrToInt(ZigClangEnumDecl_getCanonicalDecl(enum_decl)))) |name|
675 return try transCreateNodeIdentifier(c, name.value); // Avoid processing this decl twice
676 const rp = makeRestorePoint(c);
677 const enum_loc = ZigClangEnumDecl_getLocation(enum_decl);
678
679 var bare_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, enum_decl)));
680 var is_unnamed = false;
681 if (bare_name.len == 0) {
682 bare_name = try std.fmt.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()});
683 is_unnamed = true;
684 }
685
686 const name = try std.fmt.allocPrint(c.a(), "enum_{}", .{bare_name});
687 _ = try c.decl_table.put(@ptrToInt(ZigClangEnumDecl_getCanonicalDecl(enum_decl)), name);
688 const node = try transCreateNodeVarDecl(c, true, true, name);
689 node.eq_token = try appendToken(c, .Equal, "=");
690
691 node.init_node = if (ZigClangEnumDecl_getDefinition(enum_decl)) |enum_def| blk: {
692 var pure_enum = true;
693 var it = ZigClangEnumDecl_enumerator_begin(enum_def);
694 var end_it = ZigClangEnumDecl_enumerator_end(enum_def);
695 while (ZigClangEnumDecl_enumerator_iterator_neq(it, end_it)) : (it = ZigClangEnumDecl_enumerator_iterator_next(it)) {
696 const enum_const = ZigClangEnumDecl_enumerator_iterator_deref(it);
697 if (ZigClangEnumConstantDecl_getInitExpr(enum_const)) |_| {
698 pure_enum = false;
699 break;
700 }
701 }
702
703 const extern_tok = try appendToken(c, .Keyword_extern, "extern");
704 const container_tok = try appendToken(c, .Keyword_enum, "enum");
705
706 const container_node = try c.a().create(ast.Node.ContainerDecl);
707 container_node.* = .{
708 .layout_token = extern_tok,
709 .kind_token = container_tok,
710 .init_arg_expr = .None,
711 .fields_and_decls = ast.Node.ContainerDecl.DeclList.init(c.a()),
712 .lbrace_token = undefined,
713 .rbrace_token = undefined,
714 };
715
716 const int_type = ZigClangEnumDecl_getIntegerType(enum_decl);
717
718 // TODO only emit this tag type if the enum tag type is not the default.
719 // I don't know what the default is, need to figure out how clang is deciding.
720 // it appears to at least be different across gcc/msvc
721 if (!isCBuiltinType(int_type, .UInt) and
722 !isCBuiltinType(int_type, .Int))
723 {
724 _ = try appendToken(c, .LParen, "(");
725 container_node.init_arg_expr = .{
726 .Type = transQualType(rp, int_type, enum_loc) catch |err| switch (err) {
727 error.UnsupportedType => {
728 try failDecl(c, enum_loc, name, "unable to translate enum tag type", .{});
729 return null;
730 },
731 else => |e| return e,
732 },
733 };
734 _ = try appendToken(c, .RParen, ")");
735 }
736
737 container_node.lbrace_token = try appendToken(c, .LBrace, "{");
738
739 it = ZigClangEnumDecl_enumerator_begin(enum_def);
740 end_it = ZigClangEnumDecl_enumerator_end(enum_def);
741 while (ZigClangEnumDecl_enumerator_iterator_neq(it, end_it)) : (it = ZigClangEnumDecl_enumerator_iterator_next(it)) {
742 const enum_const = ZigClangEnumDecl_enumerator_iterator_deref(it);
743
744 const enum_val_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, enum_const)));
745
746 const field_name = if (!is_unnamed and std.mem.startsWith(u8, enum_val_name, bare_name))
747 enum_val_name[bare_name.len..]
748 else
749 enum_val_name;
750
751 const field_name_tok = try appendIdentifier(c, field_name);
752
753 const int_node = if (!pure_enum) blk: {
754 _ = try appendToken(c, .Colon, "=");
755 break :blk try transCreateNodeAPInt(c, ZigClangEnumConstantDecl_getInitVal(enum_const));
756 } else
757 null;
758
759 const field_node = try c.a().create(ast.Node.ContainerField);
760 field_node.* = .{
761 .doc_comments = null,
762 .comptime_token = null,
763 .name_token = field_name_tok,
764 .type_expr = null,
765 .value_expr = int_node,
766 .align_expr = null,
767 };
768
769 try container_node.fields_and_decls.push(&field_node.base);
770 _ = try appendToken(c, .Comma, ",");
771 // In C each enum value is in the global namespace. So we put them there too.
772 // At this point we can rely on the enum emitting successfully.
773 try addEnumTopLevel(c, name, field_name, enum_val_name);
774 }
775 container_node.rbrace_token = try appendToken(c, .RBrace, "}");
776
777 break :blk &container_node.base;
778 } else
779 try transCreateNodeOpaqueType(c);
780
597781 node.semicolon_token = try appendToken(c, .Semicolon, ";");
598782
599783 try addTopLevelDecl(c, name, &node.base);
600 try c.alias_list.push(.{ .alias = bare_name, .name = name });
784 if (!is_unnamed)
785 try c.alias_list.push(.{ .alias = bare_name, .name = name });
786 return transCreateNodeIdentifier(c, name);
787}
788
789fn addEnumTopLevel(c: *Context, enum_name: []const u8, field_name: []const u8, enum_val_name: []const u8) !void {
790 const node = try transCreateNodeVarDecl(c, true, true, enum_val_name);
791 node.eq_token = try appendToken(c, .Equal, "=");
792 const enum_ident = try transCreateNodeIdentifier(c, enum_name);
793 const period_tok = try appendToken(c, .Period, ".");
794 const field_ident = try transCreateNodeIdentifier(c, field_name);
795 node.semicolon_token = try appendToken(c, .Semicolon, ";");
796
797 const field_access_node = try c.a().create(ast.Node.InfixOp);
798 field_access_node.* = .{
799 .op_token = period_tok,
800 .lhs = enum_ident,
801 .op = .Period,
802 .rhs = field_ident,
803 };
804 node.init_node = &field_access_node.base;
805 try addTopLevelDecl(c, field_name, &node.base);
601806}
602807
603808fn createAlias(c: *Context, alias: var) !void {
......@@ -1452,7 +1657,6 @@ fn transSwitch(
14521657 switch_scope.pending_block.rbrace = try appendToken(rp.c, .RBrace, "}");
14531658 return &switch_scope.pending_block.base;
14541659}
1455
14561660
14571661fn transCase(
14581662 rp: RestorePoint,
......@@ -1675,222 +1879,6 @@ fn transQualType(rp: RestorePoint, qt: ZigClangQualType, source_loc: ZigClangSou
16751879 return transType(rp, ZigClangQualType_getTypePtr(qt), source_loc);
16761880}
16771881
1678fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) TypeError!*ast.Node {
1679 const rp = makeRestorePoint(c);
1680
1681 const record_loc = ZigClangRecordDecl_getLocation(record_decl);
1682
1683 var container_kind_name: []const u8 = undefined;
1684 var container_kind: std.zig.Token.Id = undefined;
1685
1686 if (ZigClangRecordDecl_isUnion(record_decl)) {
1687 container_kind_name = "union";
1688 container_kind = .Keyword_union;
1689 } else if (ZigClangRecordDecl_isStruct(record_decl)) {
1690 container_kind_name = "struct";
1691 container_kind = .Keyword_struct;
1692 } else {
1693 return revertAndWarn(
1694 rp,
1695 error.UnsupportedType,
1696 record_loc,
1697 "unsupported record type",
1698 .{},
1699 );
1700 }
1701
1702 const record_def = ZigClangRecordDecl_getDefinition(record_decl) orelse {
1703 return transCreateNodeOpaqueType(c);
1704 };
1705
1706 const extern_tok = try appendToken(c, .Keyword_extern, "extern");
1707 const container_tok = try appendToken(c, container_kind, container_kind_name);
1708 const lbrace_token = try appendToken(c, .LBrace, "{");
1709
1710 const container_node = try c.a().create(ast.Node.ContainerDecl);
1711 container_node.* = .{
1712 .layout_token = extern_tok,
1713 .kind_token = container_tok,
1714 .init_arg_expr = .None,
1715 .fields_and_decls = ast.Node.ContainerDecl.DeclList.init(c.a()),
1716 .lbrace_token = lbrace_token,
1717 .rbrace_token = undefined,
1718 };
1719
1720 var it = ZigClangRecordDecl_field_begin(record_def);
1721 const end_it = ZigClangRecordDecl_field_end(record_def);
1722 while (ZigClangRecordDecl_field_iterator_neq(it, end_it)) : (it = ZigClangRecordDecl_field_iterator_next(it)) {
1723 const field_decl = ZigClangRecordDecl_field_iterator_deref(it);
1724 const field_loc = ZigClangFieldDecl_getLocation(field_decl);
1725
1726 if (ZigClangFieldDecl_isBitField(field_decl)) {
1727 rp.activate();
1728 const node = try transCreateNodeOpaqueType(c);
1729 try emitWarning(c, field_loc, "{} demoted to opaque type - has bitfield", .{container_kind_name});
1730 return node;
1731 }
1732
1733 const field_name = try appendIdentifier(c, try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, field_decl))));
1734 _ = try appendToken(c, .Colon, ":");
1735 const field_type = try transQualType(rp, ZigClangFieldDecl_getType(field_decl), field_loc);
1736
1737 const field_node = try c.a().create(ast.Node.ContainerField);
1738 field_node.* = .{
1739 .doc_comments = null,
1740 .comptime_token = null,
1741 .name_token = field_name,
1742 .type_expr = field_type,
1743 .value_expr = null,
1744 .align_expr = null,
1745 };
1746
1747 try container_node.fields_and_decls.push(&field_node.base);
1748 _ = try appendToken(c, .Comma, ",");
1749 }
1750
1751 container_node.rbrace_token = try appendToken(c, .RBrace, "}");
1752 return &container_node.base;
1753}
1754
1755fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.Node {
1756 if (c.decl_table.get(@ptrToInt(ZigClangEnumDecl_getCanonicalDecl(enum_decl)))) |name|
1757 return try transCreateNodeIdentifier(c, name.value); // Avoid processing this decl twice
1758 const rp = makeRestorePoint(c);
1759 const enum_loc = ZigClangEnumDecl_getLocation(enum_decl);
1760
1761 var bare_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, enum_decl)));
1762 var is_unnamed = false;
1763 if (bare_name.len == 0) {
1764 bare_name = try std.fmt.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()});
1765 is_unnamed = true;
1766 }
1767
1768 const name = try std.fmt.allocPrint(c.a(), "enum_{}", .{bare_name});
1769 _ = try c.decl_table.put(@ptrToInt(ZigClangEnumDecl_getCanonicalDecl(enum_decl)), name);
1770 const node = try transCreateNodeVarDecl(c, true, true, name);
1771 node.eq_token = try appendToken(c, .Equal, "=");
1772
1773 node.init_node = if (ZigClangEnumDecl_getDefinition(enum_decl)) |enum_def| blk: {
1774 var pure_enum = true;
1775 var it = ZigClangEnumDecl_enumerator_begin(enum_def);
1776 var end_it = ZigClangEnumDecl_enumerator_end(enum_def);
1777 while (ZigClangEnumDecl_enumerator_iterator_neq(it, end_it)) : (it = ZigClangEnumDecl_enumerator_iterator_next(it)) {
1778 const enum_const = ZigClangEnumDecl_enumerator_iterator_deref(it);
1779 if (ZigClangEnumConstantDecl_getInitExpr(enum_const)) |_| {
1780 pure_enum = false;
1781 break;
1782 }
1783 }
1784
1785 const extern_tok = try appendToken(c, .Keyword_extern, "extern");
1786 const container_tok = try appendToken(c, .Keyword_enum, "enum");
1787
1788 const container_node = try c.a().create(ast.Node.ContainerDecl);
1789 container_node.* = .{
1790 .layout_token = extern_tok,
1791 .kind_token = container_tok,
1792 .init_arg_expr = .None,
1793 .fields_and_decls = ast.Node.ContainerDecl.DeclList.init(c.a()),
1794 .lbrace_token = undefined,
1795 .rbrace_token = undefined,
1796 };
1797
1798 const int_type = ZigClangEnumDecl_getIntegerType(enum_decl);
1799
1800 // TODO only emit this tag type if the enum tag type is not the default.
1801 // I don't know what the default is, need to figure out how clang is deciding.
1802 // it appears to at least be different across gcc/msvc
1803 if (!isCBuiltinType(int_type, .UInt) and
1804 !isCBuiltinType(int_type, .Int))
1805 {
1806 _ = try appendToken(c, .LParen, "(");
1807 container_node.init_arg_expr = .{
1808 .Type = transQualType(rp, int_type, enum_loc) catch |err| switch (err) {
1809 error.UnsupportedType => {
1810 if (is_unnamed) {
1811 try emitWarning(c, enum_loc, "unable to translate enum tag type", .{});
1812 } else {
1813 try failDecl(c, enum_loc, name, "unable to translate enum tag type", .{});
1814 }
1815 return null;
1816 },
1817 else => |e| return e,
1818 },
1819 };
1820 _ = try appendToken(c, .RParen, ")");
1821 }
1822
1823 container_node.lbrace_token = try appendToken(c, .LBrace, "{");
1824
1825 it = ZigClangEnumDecl_enumerator_begin(enum_def);
1826 end_it = ZigClangEnumDecl_enumerator_end(enum_def);
1827 while (ZigClangEnumDecl_enumerator_iterator_neq(it, end_it)) : (it = ZigClangEnumDecl_enumerator_iterator_next(it)) {
1828 const enum_const = ZigClangEnumDecl_enumerator_iterator_deref(it);
1829
1830 const enum_val_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, enum_const)));
1831
1832 const field_name = if (!is_unnamed and std.mem.startsWith(u8, enum_val_name, bare_name))
1833 enum_val_name[bare_name.len..]
1834 else
1835 enum_val_name;
1836
1837 const field_name_tok = try appendIdentifier(c, field_name);
1838
1839 const int_node = if (!pure_enum) blk: {
1840 _ = try appendToken(c, .Colon, "=");
1841 break :blk try transCreateNodeAPInt(c, ZigClangEnumConstantDecl_getInitVal(enum_const));
1842 } else
1843 null;
1844
1845 const field_node = try c.a().create(ast.Node.ContainerField);
1846 field_node.* = .{
1847 .doc_comments = null,
1848 .comptime_token = null,
1849 .name_token = field_name_tok,
1850 .type_expr = null,
1851 .value_expr = int_node,
1852 .align_expr = null,
1853 };
1854
1855 try container_node.fields_and_decls.push(&field_node.base);
1856 _ = try appendToken(c, .Comma, ",");
1857 // In C each enum value is in the global namespace. So we put them there too.
1858 // At this point we can rely on the enum emitting successfully.
1859 try addEnumTopLevel(c, name, field_name, enum_val_name);
1860 }
1861 container_node.rbrace_token = try appendToken(c, .RBrace, "}");
1862
1863 break :blk &container_node.base;
1864 } else
1865 try transCreateNodeOpaqueType(c);
1866
1867 node.semicolon_token = try appendToken(c, .Semicolon, ";");
1868
1869 try addTopLevelDecl(c, name, &node.base);
1870 if (!is_unnamed)
1871 try c.alias_list.push(.{ .alias = bare_name, .name = name });
1872 return transCreateNodeIdentifier(c, name);
1873}
1874
1875fn addEnumTopLevel(c: *Context, enum_name: []const u8, field_name: []const u8, enum_val_name: []const u8) !void {
1876 const node = try transCreateNodeVarDecl(c, true, true, enum_val_name);
1877 node.eq_token = try appendToken(c, .Equal, "=");
1878 const enum_ident = try transCreateNodeIdentifier(c, enum_name);
1879 const period_tok = try appendToken(c, .Period, ".");
1880 const field_ident = try transCreateNodeIdentifier(c, field_name);
1881 node.semicolon_token = try appendToken(c, .Semicolon, ";");
1882
1883 const field_access_node = try c.a().create(ast.Node.InfixOp);
1884 field_access_node.* = .{
1885 .op_token = period_tok,
1886 .lhs = enum_ident,
1887 .op = .Period,
1888 .rhs = field_ident,
1889 };
1890 node.init_node = &field_access_node.base;
1891 try addTopLevelDecl(c, field_name, &node.base);
1892}
1893
18941882fn isCBuiltinType(qt: ZigClangQualType, kind: ZigClangBuiltinTypeKind) bool {
18951883 const c_type = qualTypeCanon(qt);
18961884 if (ZigClangType_getTypeClass(c_type) != .Builtin)
......@@ -2591,7 +2579,7 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
25912579 else => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported builtin type", .{}),
25922580 });
25932581 },
2594 .FunctionProto => {
2582 .FunctionProto, .FunctionNoProto => {
25952583 const fn_proto_ty = @ptrCast(*const ZigClangFunctionProtoType, ty);
25962584 const fn_proto = try transFnProto(rp, null, fn_proto_ty, source_loc, null, false);
25972585 return &fn_proto.base;
......@@ -2666,24 +2654,15 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
26662654 const typedef_ty = @ptrCast(*const ZigClangTypedefType, ty);
26672655
26682656 const typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
2669 const typedef_name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, typedef_decl)));
2670 return transCreateNodeIdentifier(rp.c, typedef_name);
2657 return (try transTypeDef(rp.c, typedef_decl)) orelse
2658 revertAndWarn(rp, error.UnsupportedType, source_loc, "unable to translate typedef declaration", .{});
26712659 },
26722660 .Record => {
26732661 const record_ty = @ptrCast(*const ZigClangRecordType, ty);
26742662
2675 // TODO this sould get the name from decl_table
2676 // struct Foo {
2677 // struct Bar{
2678 // int b;
2679 // };
2680 // struct Bar c;
2681 // };
26822663 const record_decl = ZigClangRecordType_getDecl(record_ty);
2683 if (try getContainerName(rp, record_decl)) |name|
2684 return transCreateNodeIdentifier(rp.c, name)
2685 else
2686 return transRecordDecl(rp.c, record_decl);
2664 return (try transRecordDecl(rp.c, record_decl)) orelse
2665 revertAndWarn(rp, error.UnsupportedType, source_loc, "unable to resolve record declaration", .{});
26872666 },
26882667 .Enum => {
26892668 const enum_ty = @ptrCast(*const ZigClangEnumType, ty);
......@@ -2704,6 +2683,10 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
27042683 const attributed_ty = @ptrCast(*const ZigClangAttributedType, ty);
27052684 return transQualType(rp, ZigClangAttributedType_getEquivalentType(attributed_ty), source_loc);
27062685 },
2686 .MacroQualified => {
2687 const macroqualified_ty = @ptrCast(*const ZigClangMacroQualifiedType, ty);
2688 return transQualType(rp, ZigClangMacroQualifiedType_getModifiedType(macroqualified_ty), source_loc);
2689 },
27072690 else => {
27082691 const type_name = rp.c.str(ZigClangType_getTypeClassName(ty));
27092692 return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported type: '{}'", .{type_name});
......@@ -2711,22 +2694,6 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
27112694 }
27122695}
27132696
2714fn getContainerName(rp: RestorePoint, record_decl: *const ZigClangRecordDecl) !?[]const u8 {
2715 const bare_name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, record_decl)));
2716
2717 const container_kind_name = if (ZigClangRecordDecl_isUnion(record_decl))
2718 "union"
2719 else if (ZigClangRecordDecl_isStruct(record_decl))
2720 "struct"
2721 else
2722 return revertAndWarn(rp, error.UnsupportedType, ZigClangRecordDecl_getLocation(record_decl), "record {} is not a struct or union", .{bare_name});
2723
2724 if (ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl) or bare_name.len == 0)
2725 return null;
2726
2727 return try std.fmt.allocPrint(rp.c.a(), "{}_{}", .{ container_kind_name, bare_name });
2728}
2729
27302697fn isCVoid(qt: ZigClangQualType) bool {
27312698 const ty = ZigClangQualType_getTypePtr(qt);
27322699 if (ZigClangType_getTypeClass(ty) == .Builtin) {
......@@ -2909,14 +2876,13 @@ fn finishTransFnProto(
29092876 };
29102877
29112878 const fn_proto = try rp.c.a().create(ast.Node.FnProto);
2912 fn_proto.* = ast.Node.FnProto{
2913 .base = ast.Node{ .id = ast.Node.Id.FnProto },
2879 fn_proto.* = .{
29142880 .doc_comments = null,
29152881 .visib_token = pub_tok,
29162882 .fn_token = fn_tok,
29172883 .name_token = name_tok,
29182884 .params = fn_params,
2919 .return_type = ast.Node.FnProto.ReturnType{ .Explicit = return_type_node },
2885 .return_type = .{ .Explicit = return_type_node },
29202886 .var_args_token = null, // TODO this field is broken in the AST data model
29212887 .extern_export_inline_token = extern_export_inline_tok,
29222888 .cc_token = cc_tok,
test/translate_c.zig+21-8
......@@ -228,7 +228,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
228228 \\ struct Foo *foo;
229229 \\};
230230 , &[_][]const u8{
231 \\pub const struct_Foo = @OpaqueType()
231 \\pub const struct_Foo = @OpaqueType();
232232 ,
233233 \\pub const struct_Bar = extern struct {
234234 \\ foo: ?*struct_Foo,
......@@ -622,18 +622,15 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
622622 \\#define glClearPFN PFNGLCLEARPROC
623623 , &[_][]const u8{
624624 \\pub const GLbitfield = c_uint;
625 ,
626625 \\pub const PFNGLCLEARPROC = ?extern fn (GLbitfield) void;
627 ,
628626 \\pub const OpenGLProc = ?extern fn () void;
629 ,
627 \\pub const struct_unnamed_1 = extern struct {
628 \\ Clear: PFNGLCLEARPROC,
629 \\};
630630 \\pub const union_OpenGLProcs = extern union {
631631 \\ ptr: [1]OpenGLProc,
632 \\ gl: extern struct {
633 \\ Clear: PFNGLCLEARPROC,
634 \\ },
632 \\ gl: struct_unnamed_1,
635633 \\};
636 ,
637634 \\pub extern var glProcs: union_OpenGLProcs;
638635 ,
639636 \\pub const glClearPFN = PFNGLCLEARPROC;
......@@ -891,6 +888,22 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
891888 \\}
892889 });
893890
891 cases.add_2("type referenced struct",
892 \\struct Foo {
893 \\ struct Bar{
894 \\ int b;
895 \\ };
896 \\ struct Bar c;
897 \\};
898 , &[_][]const u8{
899 \\pub const struct_Bar = extern struct {
900 \\ b: c_int,
901 \\};
902 \\pub const struct_Foo = extern struct {
903 \\ c: struct_Bar,
904 \\};
905 });
906
894907 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
895908
896909 if (builtin.os != builtin.Os.windows) {