Commit fd3a41dadc

Jimmi Holst Christensen <jimmiholstchristensen@gmail.com>
2018-07-18 17:00:42
Allow pointers to anything in extern/exported declarations (#1258)
* type_allowed_in_extern accepts all ptr not size 0 * Generate correct headers for none extern structs/unions/enums
1 parent c393a39
Changed files (3)
src/analyze.cpp
@@ -1454,7 +1454,9 @@ static bool type_allowed_in_extern(CodeGen *g, TypeTableEntry *type_entry) {
         case TypeTableEntryIdFn:
             return type_entry->data.fn.fn_type_id.cc == CallingConventionC;
         case TypeTableEntryIdPointer:
-            return type_allowed_in_extern(g, type_entry->data.pointer.child_type);
+            if (type_size(g, type_entry) == 0)
+                return false;
+            return true;
         case TypeTableEntryIdStruct:
             return type_entry->data.structure.layout == ContainerLayoutExtern || type_entry->data.structure.layout == ContainerLayoutPacked;
         case TypeTableEntryIdOptional:
src/codegen.cpp
@@ -7508,51 +7508,60 @@ static void gen_h_file(CodeGen *g) {
             case TypeTableEntryIdPromise:
                 zig_unreachable();
             case TypeTableEntryIdEnum:
-                assert(type_entry->data.enumeration.layout == ContainerLayoutExtern);
-                fprintf(out_h, "enum %s {\n", buf_ptr(&type_entry->name));
-                for (uint32_t field_i = 0; field_i < type_entry->data.enumeration.src_field_count; field_i += 1) {
-                    TypeEnumField *enum_field = &type_entry->data.enumeration.fields[field_i];
-                    Buf *value_buf = buf_alloc();
-                    bigint_append_buf(value_buf, &enum_field->value, 10);
-                    fprintf(out_h, "    %s = %s", buf_ptr(enum_field->name), buf_ptr(value_buf));
-                    if (field_i != type_entry->data.enumeration.src_field_count - 1) {
-                        fprintf(out_h, ",");
+                if (type_entry->data.enumeration.layout == ContainerLayoutExtern) {
+                    fprintf(out_h, "enum %s {\n", buf_ptr(&type_entry->name));
+                    for (uint32_t field_i = 0; field_i < type_entry->data.enumeration.src_field_count; field_i += 1) {
+                        TypeEnumField *enum_field = &type_entry->data.enumeration.fields[field_i];
+                        Buf *value_buf = buf_alloc();
+                        bigint_append_buf(value_buf, &enum_field->value, 10);
+                        fprintf(out_h, "    %s = %s", buf_ptr(enum_field->name), buf_ptr(value_buf));
+                        if (field_i != type_entry->data.enumeration.src_field_count - 1) {
+                            fprintf(out_h, ",");
+                        }
+                        fprintf(out_h, "\n");
                     }
-                    fprintf(out_h, "\n");
+                    fprintf(out_h, "};\n\n");
+                } else {
+                    fprintf(out_h, "enum %s;\n", buf_ptr(&type_entry->name));
                 }
-                fprintf(out_h, "};\n\n");
                 break;
             case TypeTableEntryIdStruct:
-                assert(type_entry->data.structure.layout == ContainerLayoutExtern);
-                fprintf(out_h, "struct %s {\n", buf_ptr(&type_entry->name));
-                for (uint32_t field_i = 0; field_i < type_entry->data.structure.src_field_count; field_i += 1) {
-                    TypeStructField *struct_field = &type_entry->data.structure.fields[field_i];
-
-                    Buf *type_name_buf = buf_alloc();
-                    get_c_type(g, gen_h, struct_field->type_entry, type_name_buf);
-
-                    if (struct_field->type_entry->id == TypeTableEntryIdArray) {
-                        fprintf(out_h, "    %s %s[%" ZIG_PRI_u64 "];\n", buf_ptr(type_name_buf),
-                                buf_ptr(struct_field->name),
-                                struct_field->type_entry->data.array.len);
-                    } else {
-                        fprintf(out_h, "    %s %s;\n", buf_ptr(type_name_buf), buf_ptr(struct_field->name));
-                    }
+                if (type_entry->data.structure.layout == ContainerLayoutExtern) {
+                    fprintf(out_h, "struct %s {\n", buf_ptr(&type_entry->name));
+                    for (uint32_t field_i = 0; field_i < type_entry->data.structure.src_field_count; field_i += 1) {
+                        TypeStructField *struct_field = &type_entry->data.structure.fields[field_i];
+
+                        Buf *type_name_buf = buf_alloc();
+                        get_c_type(g, gen_h, struct_field->type_entry, type_name_buf);
+
+                        if (struct_field->type_entry->id == TypeTableEntryIdArray) {
+                            fprintf(out_h, "    %s %s[%" ZIG_PRI_u64 "];\n", buf_ptr(type_name_buf),
+                                    buf_ptr(struct_field->name),
+                                    struct_field->type_entry->data.array.len);
+                        } else {
+                            fprintf(out_h, "    %s %s;\n", buf_ptr(type_name_buf), buf_ptr(struct_field->name));
+                        }
 
+                    }
+                    fprintf(out_h, "};\n\n");
+                } else {
+                    fprintf(out_h, "struct %s;\n", buf_ptr(&type_entry->name));
                 }
-                fprintf(out_h, "};\n\n");
                 break;
             case TypeTableEntryIdUnion:
-                assert(type_entry->data.unionation.layout == ContainerLayoutExtern);
-                fprintf(out_h, "union %s {\n", buf_ptr(&type_entry->name));
-                for (uint32_t field_i = 0; field_i < type_entry->data.unionation.src_field_count; field_i += 1) {
-                    TypeUnionField *union_field = &type_entry->data.unionation.fields[field_i];
-
-                    Buf *type_name_buf = buf_alloc();
-                    get_c_type(g, gen_h, union_field->type_entry, type_name_buf);
-                    fprintf(out_h, "    %s %s;\n", buf_ptr(type_name_buf), buf_ptr(union_field->name));
+                if (type_entry->data.unionation.layout == ContainerLayoutExtern) {
+                    fprintf(out_h, "union %s {\n", buf_ptr(&type_entry->name));
+                    for (uint32_t field_i = 0; field_i < type_entry->data.unionation.src_field_count; field_i += 1) {
+                        TypeUnionField *union_field = &type_entry->data.unionation.fields[field_i];
+
+                        Buf *type_name_buf = buf_alloc();
+                        get_c_type(g, gen_h, union_field->type_entry, type_name_buf);
+                        fprintf(out_h, "    %s %s;\n", buf_ptr(type_name_buf), buf_ptr(union_field->name));
+                    }
+                    fprintf(out_h, "};\n\n");
+                } else {
+                    fprintf(out_h, "union %s;\n", buf_ptr(&type_entry->name));
                 }
-                fprintf(out_h, "};\n\n");
                 break;
             case TypeTableEntryIdOpaque:
                 fprintf(out_h, "struct %s;\n\n", buf_ptr(&type_entry->name));
test/gen_h.zig
@@ -76,4 +76,51 @@ pub fn addCases(cases: *tests.GenHContext) void {
         \\TEST_EXPORT void entry(struct Foo foo, uint8_t bar[]);
         \\
     );
+
+    cases.add("ptr to zig struct",
+        \\const S = struct {
+        \\    a: u8,
+        \\};
+        \\
+        \\export fn a(s: *S) u8 {
+        \\    return s.a;
+        \\}
+
+    ,
+        \\struct S;
+        \\TEST_EXPORT uint8_t a(struct S * s);
+        \\
+    );
+
+    cases.add("ptr to zig union",
+        \\const U = union(enum) {
+        \\    A: u8,
+        \\    B: u16,
+        \\};
+        \\
+        \\export fn a(s: *U) u8 {
+        \\    return s.A;
+        \\}
+
+    ,
+        \\union U;
+        \\TEST_EXPORT uint8_t a(union U * s);
+        \\
+    );
+
+    cases.add("ptr to zig enum",
+        \\const E = enum(u8) {
+        \\    A,
+        \\    B,
+        \\};
+        \\
+        \\export fn a(s: *E) u8 {
+        \\    return @enumToInt(s.*);
+        \\}
+
+    ,
+        \\enum E;
+        \\TEST_EXPORT uint8_t a(enum E * s);
+        \\
+    );
 }