| author | |
| committer | |
| log | b0fa2ff85334c2af626a313bb3254ce741435d55 |
| tree | 555b2f0b2ba5560adecadb6a11e34606e2c13997 |
| parent | 197509e1ec2d475fe646b3e1cde66a23df2520b3 |
| signature |
5 files changed, 197 insertions(+), 10 deletions(-)
src-self-hosted/clang.zig+3| ... | ... | @@ -804,6 +804,8 @@ pub extern fn ZigClangType_getPointeeType(self: ?*const struct_ZigClangType) str |
| 804 | 804 | pub extern fn ZigClangType_isVoidType(self: ?*const struct_ZigClangType) bool; |
| 805 | 805 | pub extern fn ZigClangType_getTypeClassName(self: *const struct_ZigClangType) [*:0]const u8; |
| 806 | 806 | pub extern fn ZigClangType_getAsArrayTypeUnsafe(self: *const ZigClangType) *const ZigClangArrayType; |
| 807 | pub extern fn ZigClangType_getAsRecordType(self: *const ZigClangType) ?*const ZigClangRecordType; | |
| 808 | pub extern fn ZigClangType_getAsUnionType(self: *const ZigClangType) ?*const ZigClangRecordType; | |
| 807 | 809 | pub extern fn ZigClangStmt_getBeginLoc(self: *const struct_ZigClangStmt) struct_ZigClangSourceLocation; |
| 808 | 810 | pub extern fn ZigClangStmt_getStmtClass(self: ?*const struct_ZigClangStmt) ZigClangStmtClass; |
| 809 | 811 | pub extern fn ZigClangStmt_classof_Expr(self: ?*const struct_ZigClangStmt) bool; |
| ... | ... | @@ -813,6 +815,7 @@ pub extern fn ZigClangExpr_getBeginLoc(self: *const struct_ZigClangExpr) struct_ |
| 813 | 815 | pub extern fn ZigClangInitListExpr_getInit(self: ?*const struct_ZigClangInitListExpr, i: c_uint) *const ZigClangExpr; |
| 814 | 816 | pub extern fn ZigClangInitListExpr_getArrayFiller(self: ?*const struct_ZigClangInitListExpr) *const ZigClangExpr; |
| 815 | 817 | pub extern fn ZigClangInitListExpr_getNumInits(self: ?*const struct_ZigClangInitListExpr) c_uint; |
| 818 | pub extern fn ZigClangInitListExpr_getInitializedFieldInUnion(self: ?*const struct_ZigClangInitListExpr) ?*ZigClangFieldDecl; | |
| 816 | 819 | pub extern fn ZigClangAPValue_getKind(self: ?*const struct_ZigClangAPValue) ZigClangAPValueKind; |
| 817 | 820 | pub extern fn ZigClangAPValue_getInt(self: ?*const struct_ZigClangAPValue) *const struct_ZigClangAPSInt; |
| 818 | 821 | pub extern fn ZigClangAPValue_getArrayInitializedElts(self: ?*const struct_ZigClangAPValue) c_uint; |
src-self-hosted/translate_c.zig+110-10| ... | ... | @@ -1781,6 +1781,70 @@ fn transExprCoercing( |
| 1781 | 1781 | return transExpr(rp, scope, expr, .used, .r_value); |
| 1782 | 1782 | } |
| 1783 | 1783 | |
| 1784 | fn transInitListExprRecord( | |
| 1785 | rp: RestorePoint, | |
| 1786 | scope: *Scope, | |
| 1787 | loc: ZigClangSourceLocation, | |
| 1788 | expr: *const ZigClangInitListExpr, | |
| 1789 | ty: *const ZigClangType, | |
| 1790 | used: ResultUsed, | |
| 1791 | ) TransError!*ast.Node { | |
| 1792 | var is_union_type = false; | |
| 1793 | // Unions and Structs are both represented as RecordDecl | |
| 1794 | const record_ty = ZigClangType_getAsRecordType(ty) orelse | |
| 1795 | blk: { | |
| 1796 | is_union_type = true; | |
| 1797 | break :blk ZigClangType_getAsUnionType(ty); | |
| 1798 | } orelse unreachable; | |
| 1799 | const record_decl = ZigClangRecordType_getDecl(record_ty); | |
| 1800 | const record_def = ZigClangRecordDecl_getDefinition(record_decl) orelse | |
| 1801 | unreachable; | |
| 1802 | ||
| 1803 | const ty_node = try transType(rp, ty, loc); | |
| 1804 | const init_count = ZigClangInitListExpr_getNumInits(expr); | |
| 1805 | var init_node = try transCreateNodeStructInitializer(rp.c, ty_node); | |
| 1806 | ||
| 1807 | var init_i: c_uint = 0; | |
| 1808 | var it = ZigClangRecordDecl_field_begin(record_def); | |
| 1809 | const end_it = ZigClangRecordDecl_field_end(record_def); | |
| 1810 | while (ZigClangRecordDecl_field_iterator_neq(it, end_it)) : (it = ZigClangRecordDecl_field_iterator_next(it)) { | |
| 1811 | const field_decl = ZigClangRecordDecl_field_iterator_deref(it); | |
| 1812 | ||
| 1813 | // The initializer for a union type has a single entry only | |
| 1814 | if (is_union_type and field_decl != ZigClangInitListExpr_getInitializedFieldInUnion(expr)) { | |
| 1815 | continue; | |
| 1816 | } | |
| 1817 | ||
| 1818 | assert(init_i < init_count); | |
| 1819 | const elem_expr = ZigClangInitListExpr_getInit(expr, init_i); | |
| 1820 | init_i += 1; | |
| 1821 | ||
| 1822 | // Generate the field assignment expression: | |
| 1823 | // .field_name = expr | |
| 1824 | const period_tok = try appendToken(rp.c, .Period, "."); | |
| 1825 | ||
| 1826 | const raw_name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, field_decl))); | |
| 1827 | if (raw_name.len < 1) continue; | |
| 1828 | const field_name_tok = try appendIdentifier(rp.c, raw_name); | |
| 1829 | ||
| 1830 | _ = try appendToken(rp.c, .Equal, "="); | |
| 1831 | ||
| 1832 | const field_init_node = try rp.c.a().create(ast.Node.FieldInitializer); | |
| 1833 | field_init_node.* = .{ | |
| 1834 | .period_token = period_tok, | |
| 1835 | .name_token = field_name_tok, | |
| 1836 | .expr = try transExpr(rp, scope, elem_expr, .used, .r_value), | |
| 1837 | }; | |
| 1838 | ||
| 1839 | try init_node.op.StructInitializer.push(&field_init_node.base); | |
| 1840 | _ = try appendToken(rp.c, .Comma, ","); | |
| 1841 | } | |
| 1842 | ||
| 1843 | init_node.rtoken = try appendToken(rp.c, .RBrace, "}"); | |
| 1844 | ||
| 1845 | return &init_node.base; | |
| 1846 | } | |
| 1847 | ||
| 1784 | 1848 | fn transInitListExpr( |
| 1785 | 1849 | rp: RestorePoint, |
| 1786 | 1850 | scope: *Scope, |
| ... | ... | @@ -1793,7 +1857,7 @@ fn transInitListExpr( |
| 1793 | 1857 | switch (ZigClangType_getTypeClass(qual_type)) { |
| 1794 | 1858 | .ConstantArray => {}, |
| 1795 | 1859 | .Record, .Elaborated => { |
| 1796 | return revertAndWarn(rp, error.UnsupportedType, source_loc, "TODO initListExpr for structs", .{}); | |
| 1860 | return transInitListExprRecord(rp, scope, source_loc, expr, qual_type, used); | |
| 1797 | 1861 | }, |
| 1798 | 1862 | else => { |
| 1799 | 1863 | const type_name = rp.c.str(ZigClangType_getTypeClassName(qual_type)); |
| ... | ... | @@ -1861,16 +1925,13 @@ fn transInitListExpr( |
| 1861 | 1925 | return &cat_node.base; |
| 1862 | 1926 | } |
| 1863 | 1927 | |
| 1864 | fn transImplicitValueInitExpr( | |
| 1928 | fn transZeroInitExpr( | |
| 1865 | 1929 | rp: RestorePoint, |
| 1866 | 1930 | scope: *Scope, |
| 1867 | expr: *const ZigClangExpr, | |
| 1868 | used: ResultUsed, | |
| 1931 | source_loc: ZigClangSourceLocation, | |
| 1932 | ty: *const ZigClangType, | |
| 1869 | 1933 | ) TransError!*ast.Node { |
| 1870 | const source_loc = ZigClangExpr_getBeginLoc(expr); | |
| 1871 | const qt = getExprQualType(rp.c, expr); | |
| 1872 | const ty = ZigClangQualType_getTypePtr(qt); | |
| 1873 | const node = switch (ZigClangType_getTypeClass(ty)) { | |
| 1934 | switch (ZigClangType_getTypeClass(ty)) { | |
| 1874 | 1935 | .Builtin => blk: { |
| 1875 | 1936 | const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty); |
| 1876 | 1937 | switch (ZigClangBuiltinType_getKind(builtin_ty)) { |
| ... | ... | @@ -1900,8 +1961,34 @@ fn transImplicitValueInitExpr( |
| 1900 | 1961 | } |
| 1901 | 1962 | }, |
| 1902 | 1963 | .Pointer => return transCreateNodeNullLiteral(rp.c), |
| 1903 | else => return revertAndWarn(rp, error.UnsupportedType, source_loc, "type does not have an implicit init value", .{}), | |
| 1904 | }; | |
| 1964 | .Typedef => { | |
| 1965 | const typedef_ty = @ptrCast(*const ZigClangTypedefType, ty); | |
| 1966 | const typedef_decl = ZigClangTypedefType_getDecl(typedef_ty); | |
| 1967 | return transZeroInitExpr( | |
| 1968 | rp, | |
| 1969 | scope, | |
| 1970 | source_loc, | |
| 1971 | ZigClangQualType_getTypePtr( | |
| 1972 | ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl), | |
| 1973 | ), | |
| 1974 | ); | |
| 1975 | }, | |
| 1976 | else => {}, | |
| 1977 | } | |
| 1978 | ||
| 1979 | return revertAndWarn(rp, error.UnsupportedType, source_loc, "type does not have an implicit init value", .{}); | |
| 1980 | } | |
| 1981 | ||
| 1982 | fn transImplicitValueInitExpr( | |
| 1983 | rp: RestorePoint, | |
| 1984 | scope: *Scope, | |
| 1985 | expr: *const ZigClangExpr, | |
| 1986 | used: ResultUsed, | |
| 1987 | ) TransError!*ast.Node { | |
| 1988 | const source_loc = ZigClangExpr_getBeginLoc(expr); | |
| 1989 | const qt = getExprQualType(rp.c, expr); | |
| 1990 | const ty = ZigClangQualType_getTypePtr(qt); | |
| 1991 | return transZeroInitExpr(rp, scope, source_loc, ty); | |
| 1905 | 1992 | } |
| 1906 | 1993 | |
| 1907 | 1994 | fn transIfStmt( |
| ... | ... | @@ -3484,6 +3571,19 @@ fn transCreateNodeContainerInitializer(c: *Context, dot_tok: ast.TokenIndex) !*a |
| 3484 | 3571 | return node; |
| 3485 | 3572 | } |
| 3486 | 3573 | |
| 3574 | fn transCreateNodeStructInitializer(c: *Context, ty: *ast.Node) !*ast.Node.SuffixOp { | |
| 3575 | _ = try appendToken(c, .LBrace, "{"); | |
| 3576 | const node = try c.a().create(ast.Node.SuffixOp); | |
| 3577 | node.* = ast.Node.SuffixOp{ | |
| 3578 | .lhs = .{ .node = ty }, | |
| 3579 | .op = .{ | |
| 3580 | .StructInitializer = ast.Node.SuffixOp.Op.InitList.init(c.a()), | |
| 3581 | }, | |
| 3582 | .rtoken = undefined, // set after appending values | |
| 3583 | }; | |
| 3584 | return node; | |
| 3585 | } | |
| 3586 | ||
| 3487 | 3587 | fn transCreateNodeInt(c: *Context, int: var) !*ast.Node { |
| 3488 | 3588 | const token = try appendTokenFmt(c, .IntegerLiteral, "{}", .{int}); |
| 3489 | 3589 | const node = try c.a().create(ast.Node.IntegerLiteral); |
src/zig_clang.cpp+18| ... | ... | @@ -1825,6 +1825,18 @@ const ZigClangArrayType *ZigClangType_getAsArrayTypeUnsafe(const ZigClangType *s |
| 1825 | 1825 | return reinterpret_cast<const ZigClangArrayType *>(result); |
| 1826 | 1826 | } |
| 1827 | 1827 | |
| 1828 | const ZigClangRecordType *ZigClangType_getAsRecordType(const ZigClangType *self) { | |
| 1829 | auto casted = reinterpret_cast<const clang::Type *>(self); | |
| 1830 | const clang::RecordType *result = casted->getAsStructureType(); | |
| 1831 | return reinterpret_cast<const ZigClangRecordType *>(result); | |
| 1832 | } | |
| 1833 | ||
| 1834 | const ZigClangRecordType *ZigClangType_getAsUnionType(const ZigClangType *self) { | |
| 1835 | auto casted = reinterpret_cast<const clang::Type *>(self); | |
| 1836 | const clang::RecordType *result = casted->getAsUnionType(); | |
| 1837 | return reinterpret_cast<const ZigClangRecordType *>(result); | |
| 1838 | } | |
| 1839 | ||
| 1828 | 1840 | ZigClangSourceLocation ZigClangStmt_getBeginLoc(const ZigClangStmt *self) { |
| 1829 | 1841 | auto casted = reinterpret_cast<const clang::Stmt *>(self); |
| 1830 | 1842 | return bitcast(casted->getBeginLoc()); |
| ... | ... | @@ -1898,6 +1910,12 @@ const ZigClangExpr *ZigClangInitListExpr_getArrayFiller(const ZigClangInitListEx |
| 1898 | 1910 | return reinterpret_cast<const ZigClangExpr *>(result); |
| 1899 | 1911 | } |
| 1900 | 1912 | |
| 1913 | const ZigClangFieldDecl *ZigClangInitListExpr_getInitializedFieldInUnion(const ZigClangInitListExpr *self) { | |
| 1914 | auto casted = reinterpret_cast<const clang::InitListExpr *>(self); | |
| 1915 | const clang::FieldDecl *result = casted->getInitializedFieldInUnion(); | |
| 1916 | return reinterpret_cast<const ZigClangFieldDecl *>(result); | |
| 1917 | } | |
| 1918 | ||
| 1901 | 1919 | unsigned ZigClangInitListExpr_getNumInits(const ZigClangInitListExpr *self) { |
| 1902 | 1920 | auto casted = reinterpret_cast<const clang::InitListExpr *>(self); |
| 1903 | 1921 | return casted->getNumInits(); |
src/zig_clang.h+3| ... | ... | @@ -934,6 +934,8 @@ ZIG_EXTERN_C struct ZigClangQualType ZigClangType_getPointeeType(const struct Zi |
| 934 | 934 | ZIG_EXTERN_C bool ZigClangType_isVoidType(const struct ZigClangType *self); |
| 935 | 935 | ZIG_EXTERN_C const char *ZigClangType_getTypeClassName(const struct ZigClangType *self); |
| 936 | 936 | ZIG_EXTERN_C const struct ZigClangArrayType *ZigClangType_getAsArrayTypeUnsafe(const struct ZigClangType *self); |
| 937 | ZIG_EXTERN_C const ZigClangRecordType *ZigClangType_getAsRecordType(const ZigClangType *self); | |
| 938 | ZIG_EXTERN_C const ZigClangRecordType *ZigClangType_getAsUnionType(const ZigClangType *self); | |
| 937 | 939 | |
| 938 | 940 | ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangStmt_getBeginLoc(const struct ZigClangStmt *self); |
| 939 | 941 | ZIG_EXTERN_C enum ZigClangStmtClass ZigClangStmt_getStmtClass(const struct ZigClangStmt *self); |
| ... | ... | @@ -952,6 +954,7 @@ ZIG_EXTERN_C bool ZigClangExpr_EvaluateAsConstantExpr(const struct ZigClangExpr |
| 952 | 954 | ZIG_EXTERN_C const ZigClangExpr *ZigClangInitListExpr_getInit(const ZigClangInitListExpr *, unsigned); |
| 953 | 955 | ZIG_EXTERN_C const ZigClangExpr *ZigClangInitListExpr_getArrayFiller(const ZigClangInitListExpr *); |
| 954 | 956 | ZIG_EXTERN_C unsigned ZigClangInitListExpr_getNumInits(const ZigClangInitListExpr *); |
| 957 | ZIG_EXTERN_C const ZigClangFieldDecl *ZigClangInitListExpr_getInitializedFieldInUnion(const ZigClangInitListExpr *self); | |
| 955 | 958 | |
| 956 | 959 | ZIG_EXTERN_C enum ZigClangAPValueKind ZigClangAPValue_getKind(const struct ZigClangAPValue *self); |
| 957 | 960 | ZIG_EXTERN_C const struct ZigClangAPSInt *ZigClangAPValue_getInt(const struct ZigClangAPValue *self); |
test/translate_c.zig+63| ... | ... | @@ -2,6 +2,69 @@ const tests = @import("tests.zig"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | |
| 4 | 4 | pub fn addCases(cases: *tests.TranslateCContext) void { |
| 5 | cases.add("union initializer", | |
| 6 | \\union { int x; char c[4]; } | |
| 7 | \\ ua = {1}, | |
| 8 | \\ ub = {.c={'a','b','b','a'}}; | |
| 9 | , &[_][]const u8{ | |
| 10 | \\const union_unnamed_1 = extern union { | |
| 11 | \\ x: c_int, | |
| 12 | \\ c: [4]u8, | |
| 13 | \\}; | |
| 14 | \\pub export var ua: union_unnamed_1 = union_unnamed_1{ | |
| 15 | \\ .x = @as(c_int, 1), | |
| 16 | \\}; | |
| 17 | \\pub export var ub: union_unnamed_1 = union_unnamed_1{ | |
| 18 | \\ .c = .{ | |
| 19 | \\ @bitCast(u8, @truncate(i8, @as(c_int, 'a'))), | |
| 20 | \\ @bitCast(u8, @truncate(i8, @as(c_int, 'b'))), | |
| 21 | \\ @bitCast(u8, @truncate(i8, @as(c_int, 'b'))), | |
| 22 | \\ @bitCast(u8, @truncate(i8, @as(c_int, 'a'))), | |
| 23 | \\ }, | |
| 24 | \\}; | |
| 25 | }); | |
| 26 | ||
| 27 | cases.add("struct initializer - simple", | |
| 28 | \\struct {double x,y,z;} s0 = {1.2, 1.3}; | |
| 29 | \\struct {int sec,min,hour,day,mon,year;} s1 = {.day=31,12,2014,.sec=30,15,17}; | |
| 30 | \\struct {int x,y;} s2 = {.y = 2, .x=1}; | |
| 31 | , &[_][]const u8{ | |
| 32 | \\const struct_unnamed_1 = extern struct { | |
| 33 | \\ x: f64, | |
| 34 | \\ y: f64, | |
| 35 | \\ z: f64, | |
| 36 | \\}; | |
| 37 | \\pub export var s0: struct_unnamed_1 = struct_unnamed_1{ | |
| 38 | \\ .x = 1.2, | |
| 39 | \\ .y = 1.3, | |
| 40 | \\ .z = 0, | |
| 41 | \\}; | |
| 42 | \\const struct_unnamed_2 = extern struct { | |
| 43 | \\ sec: c_int, | |
| 44 | \\ min: c_int, | |
| 45 | \\ hour: c_int, | |
| 46 | \\ day: c_int, | |
| 47 | \\ mon: c_int, | |
| 48 | \\ year: c_int, | |
| 49 | \\}; | |
| 50 | \\pub export var s1: struct_unnamed_2 = struct_unnamed_2{ | |
| 51 | \\ .sec = @as(c_int, 30), | |
| 52 | \\ .min = @as(c_int, 15), | |
| 53 | \\ .hour = @as(c_int, 17), | |
| 54 | \\ .day = @as(c_int, 31), | |
| 55 | \\ .mon = @as(c_int, 12), | |
| 56 | \\ .year = @as(c_int, 2014), | |
| 57 | \\}; | |
| 58 | \\const struct_unnamed_3 = extern struct { | |
| 59 | \\ x: c_int, | |
| 60 | \\ y: c_int, | |
| 61 | \\}; | |
| 62 | \\pub export var s2: struct_unnamed_3 = struct_unnamed_3{ | |
| 63 | \\ .x = @as(c_int, 1), | |
| 64 | \\ .y = @as(c_int, 2), | |
| 65 | \\}; | |
| 66 | }); | |
| 67 | ||
| 5 | 68 | cases.add("simple ptrCast for casts between opaque types", |
| 6 | 69 | \\struct opaque; |
| 7 | 70 | \\struct opaque_2; |