authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-01-02 17:47:53+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-01-02 14:16:39-05:00
logb0fa2ff85334c2af626a313bb3254ce741435d55
tree555b2f0b2ba5560adecadb6a11e34606e2c13997
parent197509e1ec2d475fe646b3e1cde66a23df2520b3
signaturelock-open Commit is signed but in an unrecognized format.

Translate struct/union initializer expressions


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,6 +804,8 @@ pub extern fn ZigClangType_getPointeeType(self: ?*const struct_ZigClangType) str
804pub extern fn ZigClangType_isVoidType(self: ?*const struct_ZigClangType) bool;804pub extern fn ZigClangType_isVoidType(self: ?*const struct_ZigClangType) bool;
805pub extern fn ZigClangType_getTypeClassName(self: *const struct_ZigClangType) [*:0]const u8;805pub extern fn ZigClangType_getTypeClassName(self: *const struct_ZigClangType) [*:0]const u8;
806pub extern fn ZigClangType_getAsArrayTypeUnsafe(self: *const ZigClangType) *const ZigClangArrayType;806pub extern fn ZigClangType_getAsArrayTypeUnsafe(self: *const ZigClangType) *const ZigClangArrayType;
807pub extern fn ZigClangType_getAsRecordType(self: *const ZigClangType) ?*const ZigClangRecordType;
808pub extern fn ZigClangType_getAsUnionType(self: *const ZigClangType) ?*const ZigClangRecordType;
807pub extern fn ZigClangStmt_getBeginLoc(self: *const struct_ZigClangStmt) struct_ZigClangSourceLocation;809pub extern fn ZigClangStmt_getBeginLoc(self: *const struct_ZigClangStmt) struct_ZigClangSourceLocation;
808pub extern fn ZigClangStmt_getStmtClass(self: ?*const struct_ZigClangStmt) ZigClangStmtClass;810pub extern fn ZigClangStmt_getStmtClass(self: ?*const struct_ZigClangStmt) ZigClangStmtClass;
809pub extern fn ZigClangStmt_classof_Expr(self: ?*const struct_ZigClangStmt) bool;811pub 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,6 +815,7 @@ pub extern fn ZigClangExpr_getBeginLoc(self: *const struct_ZigClangExpr) struct_
813pub extern fn ZigClangInitListExpr_getInit(self: ?*const struct_ZigClangInitListExpr, i: c_uint) *const ZigClangExpr;815pub extern fn ZigClangInitListExpr_getInit(self: ?*const struct_ZigClangInitListExpr, i: c_uint) *const ZigClangExpr;
814pub extern fn ZigClangInitListExpr_getArrayFiller(self: ?*const struct_ZigClangInitListExpr) *const ZigClangExpr;816pub extern fn ZigClangInitListExpr_getArrayFiller(self: ?*const struct_ZigClangInitListExpr) *const ZigClangExpr;
815pub extern fn ZigClangInitListExpr_getNumInits(self: ?*const struct_ZigClangInitListExpr) c_uint;817pub extern fn ZigClangInitListExpr_getNumInits(self: ?*const struct_ZigClangInitListExpr) c_uint;
818pub extern fn ZigClangInitListExpr_getInitializedFieldInUnion(self: ?*const struct_ZigClangInitListExpr) ?*ZigClangFieldDecl;
816pub extern fn ZigClangAPValue_getKind(self: ?*const struct_ZigClangAPValue) ZigClangAPValueKind;819pub extern fn ZigClangAPValue_getKind(self: ?*const struct_ZigClangAPValue) ZigClangAPValueKind;
817pub extern fn ZigClangAPValue_getInt(self: ?*const struct_ZigClangAPValue) *const struct_ZigClangAPSInt;820pub extern fn ZigClangAPValue_getInt(self: ?*const struct_ZigClangAPValue) *const struct_ZigClangAPSInt;
818pub extern fn ZigClangAPValue_getArrayInitializedElts(self: ?*const struct_ZigClangAPValue) c_uint;821pub 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,6 +1781,70 @@ fn transExprCoercing(
1781 return transExpr(rp, scope, expr, .used, .r_value);1781 return transExpr(rp, scope, expr, .used, .r_value);
1782}1782}
17831783
1784fn 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
1784fn transInitListExpr(1848fn transInitListExpr(
1785 rp: RestorePoint,1849 rp: RestorePoint,
1786 scope: *Scope,1850 scope: *Scope,
...@@ -1793,7 +1857,7 @@ fn transInitListExpr(...@@ -1793,7 +1857,7 @@ fn transInitListExpr(
1793 switch (ZigClangType_getTypeClass(qual_type)) {1857 switch (ZigClangType_getTypeClass(qual_type)) {
1794 .ConstantArray => {},1858 .ConstantArray => {},
1795 .Record, .Elaborated => {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 else => {1862 else => {
1799 const type_name = rp.c.str(ZigClangType_getTypeClassName(qual_type));1863 const type_name = rp.c.str(ZigClangType_getTypeClassName(qual_type));
...@@ -1861,16 +1925,13 @@ fn transInitListExpr(...@@ -1861,16 +1925,13 @@ fn transInitListExpr(
1861 return &cat_node.base;1925 return &cat_node.base;
1862}1926}
18631927
1864fn transImplicitValueInitExpr(1928fn transZeroInitExpr(
1865 rp: RestorePoint,1929 rp: RestorePoint,
1866 scope: *Scope,1930 scope: *Scope,
1867 expr: *const ZigClangExpr,1931 source_loc: ZigClangSourceLocation,
1868 used: ResultUsed,1932 ty: *const ZigClangType,
1869) TransError!*ast.Node {1933) TransError!*ast.Node {
1870 const source_loc = ZigClangExpr_getBeginLoc(expr);1934 switch (ZigClangType_getTypeClass(ty)) {
1871 const qt = getExprQualType(rp.c, expr);
1872 const ty = ZigClangQualType_getTypePtr(qt);
1873 const node = switch (ZigClangType_getTypeClass(ty)) {
1874 .Builtin => blk: {1935 .Builtin => blk: {
1875 const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty);1936 const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty);
1876 switch (ZigClangBuiltinType_getKind(builtin_ty)) {1937 switch (ZigClangBuiltinType_getKind(builtin_ty)) {
...@@ -1900,8 +1961,34 @@ fn transImplicitValueInitExpr(...@@ -1900,8 +1961,34 @@ fn transImplicitValueInitExpr(
1900 }1961 }
1901 },1962 },
1902 .Pointer => return transCreateNodeNullLiteral(rp.c),1963 .Pointer => return transCreateNodeNullLiteral(rp.c),
1903 else => return revertAndWarn(rp, error.UnsupportedType, source_loc, "type does not have an implicit init value", .{}),1964 .Typedef => {
1904 };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
1982fn 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}
19061993
1907fn transIfStmt(1994fn transIfStmt(
...@@ -3484,6 +3571,19 @@ fn transCreateNodeContainerInitializer(c: *Context, dot_tok: ast.TokenIndex) !*a...@@ -3484,6 +3571,19 @@ fn transCreateNodeContainerInitializer(c: *Context, dot_tok: ast.TokenIndex) !*a
3484 return node;3571 return node;
3485}3572}
34863573
3574fn 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
3487fn transCreateNodeInt(c: *Context, int: var) !*ast.Node {3587fn transCreateNodeInt(c: *Context, int: var) !*ast.Node {
3488 const token = try appendTokenFmt(c, .IntegerLiteral, "{}", .{int});3588 const token = try appendTokenFmt(c, .IntegerLiteral, "{}", .{int});
3489 const node = try c.a().create(ast.Node.IntegerLiteral);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,6 +1825,18 @@ const ZigClangArrayType *ZigClangType_getAsArrayTypeUnsafe(const ZigClangType *s
1825 return reinterpret_cast<const ZigClangArrayType *>(result);1825 return reinterpret_cast<const ZigClangArrayType *>(result);
1826}1826}
18271827
1828const 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
1834const 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
1828ZigClangSourceLocation ZigClangStmt_getBeginLoc(const ZigClangStmt *self) {1840ZigClangSourceLocation ZigClangStmt_getBeginLoc(const ZigClangStmt *self) {
1829 auto casted = reinterpret_cast<const clang::Stmt *>(self);1841 auto casted = reinterpret_cast<const clang::Stmt *>(self);
1830 return bitcast(casted->getBeginLoc());1842 return bitcast(casted->getBeginLoc());
...@@ -1898,6 +1910,12 @@ const ZigClangExpr *ZigClangInitListExpr_getArrayFiller(const ZigClangInitListEx...@@ -1898,6 +1910,12 @@ const ZigClangExpr *ZigClangInitListExpr_getArrayFiller(const ZigClangInitListEx
1898 return reinterpret_cast<const ZigClangExpr *>(result);1910 return reinterpret_cast<const ZigClangExpr *>(result);
1899}1911}
19001912
1913const 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
1901unsigned ZigClangInitListExpr_getNumInits(const ZigClangInitListExpr *self) {1919unsigned ZigClangInitListExpr_getNumInits(const ZigClangInitListExpr *self) {
1902 auto casted = reinterpret_cast<const clang::InitListExpr *>(self);1920 auto casted = reinterpret_cast<const clang::InitListExpr *>(self);
1903 return casted->getNumInits();1921 return casted->getNumInits();
src/zig_clang.h+3
...@@ -934,6 +934,8 @@ ZIG_EXTERN_C struct ZigClangQualType ZigClangType_getPointeeType(const struct Zi...@@ -934,6 +934,8 @@ ZIG_EXTERN_C struct ZigClangQualType ZigClangType_getPointeeType(const struct Zi
934ZIG_EXTERN_C bool ZigClangType_isVoidType(const struct ZigClangType *self);934ZIG_EXTERN_C bool ZigClangType_isVoidType(const struct ZigClangType *self);
935ZIG_EXTERN_C const char *ZigClangType_getTypeClassName(const struct ZigClangType *self);935ZIG_EXTERN_C const char *ZigClangType_getTypeClassName(const struct ZigClangType *self);
936ZIG_EXTERN_C const struct ZigClangArrayType *ZigClangType_getAsArrayTypeUnsafe(const struct ZigClangType *self);936ZIG_EXTERN_C const struct ZigClangArrayType *ZigClangType_getAsArrayTypeUnsafe(const struct ZigClangType *self);
937ZIG_EXTERN_C const ZigClangRecordType *ZigClangType_getAsRecordType(const ZigClangType *self);
938ZIG_EXTERN_C const ZigClangRecordType *ZigClangType_getAsUnionType(const ZigClangType *self);
937939
938ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangStmt_getBeginLoc(const struct ZigClangStmt *self);940ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangStmt_getBeginLoc(const struct ZigClangStmt *self);
939ZIG_EXTERN_C enum ZigClangStmtClass ZigClangStmt_getStmtClass(const struct ZigClangStmt *self);941ZIG_EXTERN_C enum ZigClangStmtClass ZigClangStmt_getStmtClass(const struct ZigClangStmt *self);
...@@ -952,6 +954,7 @@ ZIG_EXTERN_C bool ZigClangExpr_EvaluateAsConstantExpr(const struct ZigClangExpr...@@ -952,6 +954,7 @@ ZIG_EXTERN_C bool ZigClangExpr_EvaluateAsConstantExpr(const struct ZigClangExpr
952ZIG_EXTERN_C const ZigClangExpr *ZigClangInitListExpr_getInit(const ZigClangInitListExpr *, unsigned);954ZIG_EXTERN_C const ZigClangExpr *ZigClangInitListExpr_getInit(const ZigClangInitListExpr *, unsigned);
953ZIG_EXTERN_C const ZigClangExpr *ZigClangInitListExpr_getArrayFiller(const ZigClangInitListExpr *);955ZIG_EXTERN_C const ZigClangExpr *ZigClangInitListExpr_getArrayFiller(const ZigClangInitListExpr *);
954ZIG_EXTERN_C unsigned ZigClangInitListExpr_getNumInits(const ZigClangInitListExpr *);956ZIG_EXTERN_C unsigned ZigClangInitListExpr_getNumInits(const ZigClangInitListExpr *);
957ZIG_EXTERN_C const ZigClangFieldDecl *ZigClangInitListExpr_getInitializedFieldInUnion(const ZigClangInitListExpr *self);
955958
956ZIG_EXTERN_C enum ZigClangAPValueKind ZigClangAPValue_getKind(const struct ZigClangAPValue *self);959ZIG_EXTERN_C enum ZigClangAPValueKind ZigClangAPValue_getKind(const struct ZigClangAPValue *self);
957ZIG_EXTERN_C const struct ZigClangAPSInt *ZigClangAPValue_getInt(const struct ZigClangAPValue *self);960ZIG_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,6 +2,69 @@ const tests = @import("tests.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
33
4pub fn addCases(cases: *tests.TranslateCContext) void {4pub 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 cases.add("simple ptrCast for casts between opaque types",68 cases.add("simple ptrCast for casts between opaque types",
6 \\struct opaque;69 \\struct opaque;
7 \\struct opaque_2;70 \\struct opaque_2;