Commit 285e2f62ba

Andrew Kelley <andrew@ziglang.org>
2019-02-12 06:51:06
disallow C pointers to non-C-ABI-compatible element types
See #1059
1 parent 0abe6d6
src/analyze.cpp
@@ -1469,7 +1469,7 @@ static bool type_allowed_in_packed_struct(ZigType *type_entry) {
     zig_unreachable();
 }
 
-static bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
+bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
     switch (type_entry->id) {
         case ZigTypeIdInvalid:
             zig_unreachable();
src/analyze.hpp
@@ -44,7 +44,7 @@ void find_libc_include_path(CodeGen *g);
 void find_libc_lib_path(CodeGen *g);
 
 bool type_has_bits(ZigType *type_entry);
-
+bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry);
 
 ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *abs_full_path, Buf *source_code);
 
src/ir.cpp
@@ -21145,6 +21145,10 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct
     } else if (child_type->id == ZigTypeIdOpaque && instruction->ptr_len == PtrLenUnknown) {
         ir_add_error(ira, &instruction->base, buf_sprintf("unknown-length pointer to opaque"));
         return ira->codegen->invalid_instruction;
+    } else if (instruction->ptr_len == PtrLenC && !type_allowed_in_extern(ira->codegen, child_type)) {
+        ir_add_error(ira, &instruction->base,
+            buf_sprintf("C pointers cannot point to non-C-ABI-compatible type '%s'", buf_ptr(&child_type->name)));
+        return ira->codegen->invalid_instruction;
     }
 
     uint32_t align_bytes;
test/compile_errors.zig
@@ -1,6 +1,16 @@
 const tests = @import("tests.zig");
 
 pub fn addCases(cases: *tests.CompileErrorContext) void {
+    cases.addTest(
+        "C pointer pointing to non C ABI compatible type",
+        \\const Foo = struct {};
+        \\export fn entry() [*c]Foo {
+        \\    return undefined;
+        \\}
+    ,
+        ".tmp_source.zig:2:19: error: C pointers cannot point to non-C-ABI-compatible type 'Foo'",
+    );
+
     cases.addTest(
         "@truncate undefined value",
         \\export fn entry() void {