Skip to content

Better InitListExpr translation #4078

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src-self-hosted/clang.zig
Original file line number Diff line number Diff line change
Expand Up @@ -802,6 +802,8 @@ pub extern fn ZigClangQualType_isRestrictQualified(self: struct_ZigClangQualType
pub extern fn ZigClangType_getTypeClass(self: ?*const struct_ZigClangType) ZigClangTypeClass;
pub extern fn ZigClangType_getPointeeType(self: ?*const struct_ZigClangType) struct_ZigClangQualType;
pub extern fn ZigClangType_isVoidType(self: ?*const struct_ZigClangType) bool;
pub extern fn ZigClangType_isRecordType(self: ?*const struct_ZigClangType) bool;
pub extern fn ZigClangType_isArrayType(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;
Expand Down
56 changes: 39 additions & 17 deletions src-self-hosted/translate_c.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1851,30 +1851,18 @@ fn transInitListExprRecord(
return &init_node.base;
}

fn transInitListExpr(
fn transInitListExprArray(
rp: RestorePoint,
scope: *Scope,
loc: ZigClangSourceLocation,
expr: *const ZigClangInitListExpr,
ty: *const ZigClangType,
used: ResultUsed,
) TransError!*ast.Node {
const qt = getExprQualType(rp.c, @ptrCast(*const ZigClangExpr, expr));
const qual_type = ZigClangQualType_getTypePtr(qt);
const source_loc = ZigClangExpr_getBeginLoc(@ptrCast(*const ZigClangExpr, expr));
switch (ZigClangType_getTypeClass(qual_type)) {
.ConstantArray => {},
.Record, .Elaborated => {
return transInitListExprRecord(rp, scope, source_loc, expr, qual_type, used);
},
else => {
const type_name = rp.c.str(ZigClangType_getTypeClassName(qual_type));
return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported initlist type: '{}'", .{type_name});
},
}

const arr_type = ZigClangType_getAsArrayTypeUnsafe(qual_type);
const arr_type = ZigClangType_getAsArrayTypeUnsafe(ty);
const child_qt = ZigClangArrayType_getElementType(arr_type);
const init_count = ZigClangInitListExpr_getNumInits(expr);
const const_arr_ty = @ptrCast(*const ZigClangConstantArrayType, qual_type);
const const_arr_ty = @ptrCast(*const ZigClangConstantArrayType, ty);
const size_ap_int = ZigClangConstantArrayType_getSize(const_arr_ty);
const all_count = ZigClangAPInt_getLimitedValue(size_ap_int, math.maxInt(usize));
const leftover_count = all_count - init_count;
Expand Down Expand Up @@ -1931,6 +1919,40 @@ fn transInitListExpr(
return &cat_node.base;
}

fn transInitListExpr(
rp: RestorePoint,
scope: *Scope,
expr: *const ZigClangInitListExpr,
used: ResultUsed,
) TransError!*ast.Node {
const qt = getExprQualType(rp.c, @ptrCast(*const ZigClangExpr, expr));
var qual_type = ZigClangQualType_getTypePtr(qt);
const source_loc = ZigClangExpr_getBeginLoc(@ptrCast(*const ZigClangExpr, expr));

if (ZigClangType_isRecordType(qual_type)) {
return transInitListExprRecord(
rp,
scope,
source_loc,
expr,
qual_type,
used,
);
} else if (ZigClangType_isArrayType(qual_type)) {
return transInitListExprArray(
rp,
scope,
source_loc,
expr,
qual_type,
used,
);
} else {
const type_name = rp.c.str(ZigClangType_getTypeClassName(qual_type));
return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported initlist type: '{}'", .{type_name});
}
}

fn transZeroInitExpr(
rp: RestorePoint,
scope: *Scope,
Expand Down
10 changes: 10 additions & 0 deletions src/zig_clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1814,6 +1814,16 @@ bool ZigClangType_isVoidType(const ZigClangType *self) {
return casted->isVoidType();
}

bool ZigClangType_isArrayType(const ZigClangType *self) {
auto casted = reinterpret_cast<const clang::Type *>(self);
return casted->isArrayType();
}

bool ZigClangType_isRecordType(const ZigClangType *self) {
auto casted = reinterpret_cast<const clang::Type *>(self);
return casted->isRecordType();
}

const char *ZigClangType_getTypeClassName(const ZigClangType *self) {
auto casted = reinterpret_cast<const clang::Type *>(self);
return casted->getTypeClassName();
Expand Down
2 changes: 2 additions & 0 deletions src/zig_clang.h
Original file line number Diff line number Diff line change
Expand Up @@ -932,6 +932,8 @@ ZIG_EXTERN_C bool ZigClangQualType_isRestrictQualified(struct ZigClangQualType);
ZIG_EXTERN_C enum ZigClangTypeClass ZigClangType_getTypeClass(const struct ZigClangType *self);
ZIG_EXTERN_C struct ZigClangQualType ZigClangType_getPointeeType(const struct ZigClangType *self);
ZIG_EXTERN_C bool ZigClangType_isVoidType(const struct ZigClangType *self);
ZIG_EXTERN_C bool ZigClangType_isArrayType(const struct ZigClangType *self);
ZIG_EXTERN_C bool ZigClangType_isRecordType(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);
Expand Down
19 changes: 14 additions & 5 deletions test/translate_c.zig
Original file line number Diff line number Diff line change
Expand Up @@ -31,44 +31,53 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
});

cases.add("struct initializer - simple",
\\typedef struct { int x; } foo;
\\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};
\\foo s3 = { 123 };
, &[_][]const u8{
\\const struct_unnamed_1 = extern struct {
\\ x: c_int,
\\};
\\pub const foo = struct_unnamed_1;
\\const struct_unnamed_2 = extern struct {
\\ x: f64,
\\ y: f64,
\\ z: f64,
\\};
\\pub export var s0: struct_unnamed_1 = struct_unnamed_1{
\\pub export var s0: struct_unnamed_2 = struct_unnamed_2{
\\ .x = 1.2,
\\ .y = 1.3,
\\ .z = 0,
\\};
\\const struct_unnamed_2 = extern struct {
\\const struct_unnamed_3 = 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{
\\pub export var s1: struct_unnamed_3 = struct_unnamed_3{
\\ .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 {
\\const struct_unnamed_4 = extern struct {
\\ x: c_int,
\\ y: c_int,
\\};
\\pub export var s2: struct_unnamed_3 = struct_unnamed_3{
\\pub export var s2: struct_unnamed_4 = struct_unnamed_4{
\\ .x = @as(c_int, 1),
\\ .y = @as(c_int, 2),
\\};
\\pub export var s3: foo = foo{
\\ .x = @as(c_int, 123),
\\};
});

cases.add("simple ptrCast for casts between opaque types",
Expand Down