Commit 6ff70d3c31

LemonBoy <thatlemon@gmail.com>
2020-01-05 11:39:01
Better InitListExpr translation
1 parent 5888d84
Changed files (5)
src/zig_clang.cpp
@@ -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();
src/zig_clang.h
@@ -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);
src-self-hosted/clang.zig
@@ -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;
src-self-hosted/translate_c.zig
@@ -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;
@@ -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,
test/translate_c.zig
@@ -31,21 +31,27 @@ 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,
@@ -53,7 +59,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\    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),
@@ -61,14 +67,17 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\    .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",