mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 22:35:24 +00:00
Translate struct/union initializer expressions
This commit is contained in:
parent
197509e1ec
commit
b0fa2ff853
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user