Commit b0fa2ff853
Changed files (5)
src/zig_clang.cpp
@@ -1825,6 +1825,18 @@ const ZigClangArrayType *ZigClangType_getAsArrayTypeUnsafe(const ZigClangType *s
return reinterpret_cast<const ZigClangArrayType *>(result);
}
+const ZigClangRecordType *ZigClangType_getAsRecordType(const ZigClangType *self) {
+ auto casted = reinterpret_cast<const clang::Type *>(self);
+ const clang::RecordType *result = casted->getAsStructureType();
+ return reinterpret_cast<const ZigClangRecordType *>(result);
+}
+
+const ZigClangRecordType *ZigClangType_getAsUnionType(const ZigClangType *self) {
+ auto casted = reinterpret_cast<const clang::Type *>(self);
+ const clang::RecordType *result = casted->getAsUnionType();
+ return reinterpret_cast<const ZigClangRecordType *>(result);
+}
+
ZigClangSourceLocation ZigClangStmt_getBeginLoc(const ZigClangStmt *self) {
auto casted = reinterpret_cast<const clang::Stmt *>(self);
return bitcast(casted->getBeginLoc());
@@ -1898,6 +1910,12 @@ const ZigClangExpr *ZigClangInitListExpr_getArrayFiller(const ZigClangInitListEx
return reinterpret_cast<const ZigClangExpr *>(result);
}
+const ZigClangFieldDecl *ZigClangInitListExpr_getInitializedFieldInUnion(const ZigClangInitListExpr *self) {
+ auto casted = reinterpret_cast<const clang::InitListExpr *>(self);
+ const clang::FieldDecl *result = casted->getInitializedFieldInUnion();
+ return reinterpret_cast<const ZigClangFieldDecl *>(result);
+}
+
unsigned ZigClangInitListExpr_getNumInits(const ZigClangInitListExpr *self) {
auto casted = reinterpret_cast<const clang::InitListExpr *>(self);
return casted->getNumInits();
src/zig_clang.h
@@ -934,6 +934,8 @@ ZIG_EXTERN_C struct ZigClangQualType ZigClangType_getPointeeType(const struct Zi
ZIG_EXTERN_C bool ZigClangType_isVoidType(const struct ZigClangType *self);
ZIG_EXTERN_C const char *ZigClangType_getTypeClassName(const struct ZigClangType *self);
ZIG_EXTERN_C const struct ZigClangArrayType *ZigClangType_getAsArrayTypeUnsafe(const struct ZigClangType *self);
+ZIG_EXTERN_C const ZigClangRecordType *ZigClangType_getAsRecordType(const ZigClangType *self);
+ZIG_EXTERN_C const ZigClangRecordType *ZigClangType_getAsUnionType(const ZigClangType *self);
ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangStmt_getBeginLoc(const struct ZigClangStmt *self);
ZIG_EXTERN_C enum ZigClangStmtClass ZigClangStmt_getStmtClass(const struct ZigClangStmt *self);
@@ -952,6 +954,7 @@ ZIG_EXTERN_C bool ZigClangExpr_EvaluateAsConstantExpr(const struct ZigClangExpr
ZIG_EXTERN_C const ZigClangExpr *ZigClangInitListExpr_getInit(const ZigClangInitListExpr *, unsigned);
ZIG_EXTERN_C const ZigClangExpr *ZigClangInitListExpr_getArrayFiller(const ZigClangInitListExpr *);
ZIG_EXTERN_C unsigned ZigClangInitListExpr_getNumInits(const ZigClangInitListExpr *);
+ZIG_EXTERN_C const ZigClangFieldDecl *ZigClangInitListExpr_getInitializedFieldInUnion(const ZigClangInitListExpr *self);
ZIG_EXTERN_C enum ZigClangAPValueKind ZigClangAPValue_getKind(const struct ZigClangAPValue *self);
ZIG_EXTERN_C const struct ZigClangAPSInt *ZigClangAPValue_getInt(const struct ZigClangAPValue *self);
src-self-hosted/clang.zig
@@ -804,6 +804,8 @@ pub extern fn ZigClangType_getPointeeType(self: ?*const struct_ZigClangType) str
pub extern fn ZigClangType_isVoidType(self: ?*const struct_ZigClangType) bool;
pub extern fn ZigClangType_getTypeClassName(self: *const struct_ZigClangType) [*:0]const u8;
pub extern fn ZigClangType_getAsArrayTypeUnsafe(self: *const ZigClangType) *const ZigClangArrayType;
+pub extern fn ZigClangType_getAsRecordType(self: *const ZigClangType) ?*const ZigClangRecordType;
+pub extern fn ZigClangType_getAsUnionType(self: *const ZigClangType) ?*const ZigClangRecordType;
pub extern fn ZigClangStmt_getBeginLoc(self: *const struct_ZigClangStmt) struct_ZigClangSourceLocation;
pub extern fn ZigClangStmt_getStmtClass(self: ?*const struct_ZigClangStmt) ZigClangStmtClass;
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_
pub extern fn ZigClangInitListExpr_getInit(self: ?*const struct_ZigClangInitListExpr, i: c_uint) *const ZigClangExpr;
pub extern fn ZigClangInitListExpr_getArrayFiller(self: ?*const struct_ZigClangInitListExpr) *const ZigClangExpr;
pub extern fn ZigClangInitListExpr_getNumInits(self: ?*const struct_ZigClangInitListExpr) c_uint;
+pub extern fn ZigClangInitListExpr_getInitializedFieldInUnion(self: ?*const struct_ZigClangInitListExpr) ?*ZigClangFieldDecl;
pub extern fn ZigClangAPValue_getKind(self: ?*const struct_ZigClangAPValue) ZigClangAPValueKind;
pub extern fn ZigClangAPValue_getInt(self: ?*const struct_ZigClangAPValue) *const struct_ZigClangAPSInt;
pub extern fn ZigClangAPValue_getArrayInitializedElts(self: ?*const struct_ZigClangAPValue) c_uint;
src-self-hosted/translate_c.zig
@@ -1781,6 +1781,70 @@ fn transExprCoercing(
return transExpr(rp, scope, expr, .used, .r_value);
}
+fn transInitListExprRecord(
+ rp: RestorePoint,
+ scope: *Scope,
+ loc: ZigClangSourceLocation,
+ expr: *const ZigClangInitListExpr,
+ ty: *const ZigClangType,
+ used: ResultUsed,
+) TransError!*ast.Node {
+ var is_union_type = false;
+ // Unions and Structs are both represented as RecordDecl
+ const record_ty = ZigClangType_getAsRecordType(ty) orelse
+ blk: {
+ is_union_type = true;
+ break :blk ZigClangType_getAsUnionType(ty);
+ } orelse unreachable;
+ const record_decl = ZigClangRecordType_getDecl(record_ty);
+ const record_def = ZigClangRecordDecl_getDefinition(record_decl) orelse
+ unreachable;
+
+ const ty_node = try transType(rp, ty, loc);
+ const init_count = ZigClangInitListExpr_getNumInits(expr);
+ var init_node = try transCreateNodeStructInitializer(rp.c, ty_node);
+
+ var init_i: c_uint = 0;
+ var it = ZigClangRecordDecl_field_begin(record_def);
+ const end_it = ZigClangRecordDecl_field_end(record_def);
+ while (ZigClangRecordDecl_field_iterator_neq(it, end_it)) : (it = ZigClangRecordDecl_field_iterator_next(it)) {
+ const field_decl = ZigClangRecordDecl_field_iterator_deref(it);
+
+ // The initializer for a union type has a single entry only
+ if (is_union_type and field_decl != ZigClangInitListExpr_getInitializedFieldInUnion(expr)) {
+ continue;
+ }
+
+ assert(init_i < init_count);
+ const elem_expr = ZigClangInitListExpr_getInit(expr, init_i);
+ init_i += 1;
+
+ // Generate the field assignment expression:
+ // .field_name = expr
+ const period_tok = try appendToken(rp.c, .Period, ".");
+
+ const raw_name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, field_decl)));
+ if (raw_name.len < 1) continue;
+ const field_name_tok = try appendIdentifier(rp.c, raw_name);
+
+ _ = try appendToken(rp.c, .Equal, "=");
+
+ const field_init_node = try rp.c.a().create(ast.Node.FieldInitializer);
+ field_init_node.* = .{
+ .period_token = period_tok,
+ .name_token = field_name_tok,
+ .expr = try transExpr(rp, scope, elem_expr, .used, .r_value),
+ };
+
+ try init_node.op.StructInitializer.push(&field_init_node.base);
+ _ = try appendToken(rp.c, .Comma, ",");
+ }
+
+ init_node.rtoken = try appendToken(rp.c, .RBrace, "}");
+
+ return &init_node.base;
+}
+
fn transInitListExpr(
rp: RestorePoint,
scope: *Scope,
@@ -1793,7 +1857,7 @@ fn transInitListExpr(
switch (ZigClangType_getTypeClass(qual_type)) {
.ConstantArray => {},
.Record, .Elaborated => {
- return revertAndWarn(rp, error.UnsupportedType, source_loc, "TODO initListExpr for structs", .{});
+ return transInitListExprRecord(rp, scope, source_loc, expr, qual_type, used);
},
else => {
const type_name = rp.c.str(ZigClangType_getTypeClassName(qual_type));
@@ -1861,16 +1925,13 @@ fn transInitListExpr(
return &cat_node.base;
}
-fn transImplicitValueInitExpr(
+fn transZeroInitExpr(
rp: RestorePoint,
scope: *Scope,
- expr: *const ZigClangExpr,
- used: ResultUsed,
+ source_loc: ZigClangSourceLocation,
+ ty: *const ZigClangType,
) TransError!*ast.Node {
- const source_loc = ZigClangExpr_getBeginLoc(expr);
- const qt = getExprQualType(rp.c, expr);
- const ty = ZigClangQualType_getTypePtr(qt);
- const node = switch (ZigClangType_getTypeClass(ty)) {
+ switch (ZigClangType_getTypeClass(ty)) {
.Builtin => blk: {
const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty);
switch (ZigClangBuiltinType_getKind(builtin_ty)) {
@@ -1900,8 +1961,34 @@ fn transImplicitValueInitExpr(
}
},
.Pointer => return transCreateNodeNullLiteral(rp.c),
- else => return revertAndWarn(rp, error.UnsupportedType, source_loc, "type does not have an implicit init value", .{}),
- };
+ .Typedef => {
+ const typedef_ty = @ptrCast(*const ZigClangTypedefType, ty);
+ const typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
+ return transZeroInitExpr(
+ rp,
+ scope,
+ source_loc,
+ ZigClangQualType_getTypePtr(
+ ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl),
+ ),
+ );
+ },
+ else => {},
+ }
+
+ return revertAndWarn(rp, error.UnsupportedType, source_loc, "type does not have an implicit init value", .{});
+}
+
+fn transImplicitValueInitExpr(
+ rp: RestorePoint,
+ scope: *Scope,
+ expr: *const ZigClangExpr,
+ used: ResultUsed,
+) TransError!*ast.Node {
+ const source_loc = ZigClangExpr_getBeginLoc(expr);
+ const qt = getExprQualType(rp.c, expr);
+ const ty = ZigClangQualType_getTypePtr(qt);
+ return transZeroInitExpr(rp, scope, source_loc, ty);
}
fn transIfStmt(
@@ -3484,6 +3571,19 @@ fn transCreateNodeContainerInitializer(c: *Context, dot_tok: ast.TokenIndex) !*a
return node;
}
+fn transCreateNodeStructInitializer(c: *Context, ty: *ast.Node) !*ast.Node.SuffixOp {
+ _ = try appendToken(c, .LBrace, "{");
+ const node = try c.a().create(ast.Node.SuffixOp);
+ node.* = ast.Node.SuffixOp{
+ .lhs = .{ .node = ty },
+ .op = .{
+ .StructInitializer = ast.Node.SuffixOp.Op.InitList.init(c.a()),
+ },
+ .rtoken = undefined, // set after appending values
+ };
+ return node;
+}
+
fn transCreateNodeInt(c: *Context, int: var) !*ast.Node {
const token = try appendTokenFmt(c, .IntegerLiteral, "{}", .{int});
const node = try c.a().create(ast.Node.IntegerLiteral);
test/translate_c.zig
@@ -2,6 +2,69 @@ const tests = @import("tests.zig");
const builtin = @import("builtin");
pub fn addCases(cases: *tests.TranslateCContext) void {
+ cases.add("union initializer",
+ \\union { int x; char c[4]; }
+ \\ ua = {1},
+ \\ ub = {.c={'a','b','b','a'}};
+ , &[_][]const u8{
+ \\const union_unnamed_1 = extern union {
+ \\ x: c_int,
+ \\ c: [4]u8,
+ \\};
+ \\pub export var ua: union_unnamed_1 = union_unnamed_1{
+ \\ .x = @as(c_int, 1),
+ \\};
+ \\pub export var ub: union_unnamed_1 = union_unnamed_1{
+ \\ .c = .{
+ \\ @bitCast(u8, @truncate(i8, @as(c_int, 'a'))),
+ \\ @bitCast(u8, @truncate(i8, @as(c_int, 'b'))),
+ \\ @bitCast(u8, @truncate(i8, @as(c_int, 'b'))),
+ \\ @bitCast(u8, @truncate(i8, @as(c_int, 'a'))),
+ \\ },
+ \\};
+ });
+
+ cases.add("struct initializer - simple",
+ \\struct {double x,y,z;} s0 = {1.2, 1.3};
+ \\struct {int sec,min,hour,day,mon,year;} s1 = {.day=31,12,2014,.sec=30,15,17};
+ \\struct {int x,y;} s2 = {.y = 2, .x=1};
+ , &[_][]const u8{
+ \\const struct_unnamed_1 = extern struct {
+ \\ x: f64,
+ \\ y: f64,
+ \\ z: f64,
+ \\};
+ \\pub export var s0: struct_unnamed_1 = struct_unnamed_1{
+ \\ .x = 1.2,
+ \\ .y = 1.3,
+ \\ .z = 0,
+ \\};
+ \\const struct_unnamed_2 = extern struct {
+ \\ sec: c_int,
+ \\ min: c_int,
+ \\ hour: c_int,
+ \\ day: c_int,
+ \\ mon: c_int,
+ \\ year: c_int,
+ \\};
+ \\pub export var s1: struct_unnamed_2 = struct_unnamed_2{
+ \\ .sec = @as(c_int, 30),
+ \\ .min = @as(c_int, 15),
+ \\ .hour = @as(c_int, 17),
+ \\ .day = @as(c_int, 31),
+ \\ .mon = @as(c_int, 12),
+ \\ .year = @as(c_int, 2014),
+ \\};
+ \\const struct_unnamed_3 = extern struct {
+ \\ x: c_int,
+ \\ y: c_int,
+ \\};
+ \\pub export var s2: struct_unnamed_3 = struct_unnamed_3{
+ \\ .x = @as(c_int, 1),
+ \\ .y = @as(c_int, 2),
+ \\};
+ });
+
cases.add("simple ptrCast for casts between opaque types",
\\struct opaque;
\\struct opaque_2;