authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-14 23:09:12-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-14 23:09:31-05:00
logd6e0d82c328b4f9d733364382cce0941a601e91a
treeba5848ece64d705fa436fa4924b8e59a1a9a3dce
parentd5bbd748711abc82272199869cf70faf1ea30f52
signature Commit is signed but in an unrecognized format.

translate-c: back to *c_void for opaque types

See #1059

5 files changed, 62 insertions(+), 17 deletions(-)

src/analyze.cpp+1-1
......@@ -437,7 +437,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
437437 // move this to a parameter
438438 bool allow_zero = (ptr_len == PtrLenC);
439439 assert(!type_is_invalid(child_type));
440 assert(ptr_len != PtrLenUnknown || child_type->id != ZigTypeIdOpaque);
440 assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque);
441441
442442 if (byte_alignment != 0) {
443443 uint32_t abi_alignment = get_abi_alignment(g, child_type);
src/ir.cpp+9-4
......@@ -21205,10 +21205,15 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct
2120521205 } else if (child_type->id == ZigTypeIdOpaque && instruction->ptr_len == PtrLenUnknown) {
2120621206 ir_add_error(ira, &instruction->base, buf_sprintf("unknown-length pointer to opaque"));
2120721207 return ira->codegen->invalid_instruction;
21208 } else if (instruction->ptr_len == PtrLenC && !type_allowed_in_extern(ira->codegen, child_type)) {
21209 ir_add_error(ira, &instruction->base,
21210 buf_sprintf("C pointers cannot point to non-C-ABI-compatible type '%s'", buf_ptr(&child_type->name)));
21211 return ira->codegen->invalid_instruction;
21208 } else if (instruction->ptr_len == PtrLenC) {
21209 if (!type_allowed_in_extern(ira->codegen, child_type)) {
21210 ir_add_error(ira, &instruction->base,
21211 buf_sprintf("C pointers cannot point to non-C-ABI-compatible type '%s'", buf_ptr(&child_type->name)));
21212 return ira->codegen->invalid_instruction;
21213 } else if (child_type->id == ZigTypeIdOpaque) {
21214 ir_add_error(ira, &instruction->base, buf_sprintf("C pointers cannot point opaque types"));
21215 return ira->codegen->invalid_instruction;
21216 }
2121221217 }
2121321218
2121421219 uint32_t align_bytes;
src/translate_c.cpp+32-2
......@@ -763,6 +763,30 @@ static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) {
763763 }
764764}
765765
766static bool type_is_opaque(Context *c, const Type *ty, const SourceLocation &source_loc) {
767 switch (ty->getTypeClass()) {
768 case Type::Builtin: {
769 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty);
770 return builtin_ty->getKind() == BuiltinType::Void;
771 }
772 case Type::Record: {
773 const RecordType *record_ty = static_cast<const RecordType*>(ty);
774 return record_ty->getDecl()->getDefinition() == nullptr;
775 }
776 case Type::Elaborated: {
777 const ElaboratedType *elaborated_ty = static_cast<const ElaboratedType*>(ty);
778 return type_is_opaque(c, elaborated_ty->getNamedType().getTypePtr(), source_loc);
779 }
780 case Type::Typedef: {
781 const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty);
782 const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
783 return type_is_opaque(c, typedef_decl->getUnderlyingType().getTypePtr(), source_loc);
784 }
785 default:
786 return false;
787 }
788}
789
766790static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &source_loc) {
767791 switch (ty->getTypeClass()) {
768792 case Type::Builtin:
......@@ -912,8 +936,14 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
912936 return trans_create_node_prefix_op(c, PrefixOpOptional, child_node);
913937 }
914938
915 return trans_create_node_ptr_type(c, child_qt.isConstQualified(),
916 child_qt.isVolatileQualified(), child_node, PtrLenC);
939 if (type_is_opaque(c, child_qt.getTypePtr(), source_loc)) {
940 AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(),
941 child_qt.isVolatileQualified(), child_node, PtrLenSingle);
942 return trans_create_node_prefix_op(c, PrefixOpOptional, pointer_node);
943 } else {
944 return trans_create_node_ptr_type(c, child_qt.isConstQualified(),
945 child_qt.isVolatileQualified(), child_node, PtrLenC);
946 }
917947 }
918948 case Type::Typedef:
919949 {
test/compile_errors.zig+10
......@@ -1,6 +1,16 @@
11const tests = @import("tests.zig");
22
33pub fn addCases(cases: *tests.CompileErrorContext) void {
4 cases.addTest(
5 "C pointer to c_void",
6 \\export fn a() void {
7 \\ var x: *c_void = undefined;
8 \\ var y: [*c]c_void = x;
9 \\}
10 ,
11 ".tmp_source.zig:3:12: error: C pointers cannot point opaque types",
12 );
13
414 cases.addTest(
515 "directly embedding opaque type in struct and union",
616 \\const O = @OpaqueType();
test/translate_c.zig+10-10
......@@ -202,7 +202,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
202202 cases.add("restrict -> noalias",
203203 \\void foo(void *restrict bar, void *restrict);
204204 ,
205 \\pub extern fn foo(noalias bar: [*c]c_void, noalias arg1: [*c]c_void) void;
205 \\pub extern fn foo(noalias bar: ?*c_void, noalias arg1: ?*c_void) void;
206206 );
207207
208208 cases.add("simple struct",
......@@ -275,7 +275,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
275275 ,
276276 \\pub const struct_Foo = @OpaqueType();
277277 ,
278 \\pub extern fn some_func(foo: [*c]struct_Foo, x: c_int) [*c]struct_Foo;
278 \\pub extern fn some_func(foo: ?*struct_Foo, x: c_int) ?*struct_Foo;
279279 ,
280280 \\pub const Foo = struct_Foo;
281281 );
......@@ -336,7 +336,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
336336 ,
337337 \\pub const Foo = c_void;
338338 ,
339 \\pub extern fn fun(a: [*c]Foo) Foo;
339 \\pub extern fn fun(a: ?*Foo) Foo;
340340 );
341341
342342 cases.add("generate inline func for #define global extern fn",
......@@ -608,7 +608,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
608608 \\ return 6;
609609 \\}
610610 ,
611 \\pub export fn and_or_none_bool(a: c_int, b: f32, c: [*c]c_void) c_int {
611 \\pub export fn and_or_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
612612 \\ if ((a != 0) and (b != 0)) return 0;
613613 \\ if ((b != 0) and (c != 0)) return 1;
614614 \\ if ((a != 0) and (c != 0)) return 2;
......@@ -756,8 +756,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
756756 \\ return x;
757757 \\}
758758 ,
759 \\pub export fn foo(x: [*c]c_ushort) [*c]c_void {
760 \\ return @ptrCast([*c]c_void, x);
759 \\pub export fn foo(x: [*c]c_ushort) ?*c_void {
760 \\ return @ptrCast(?*c_void, x);
761761 \\}
762762 );
763763
......@@ -1276,7 +1276,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
12761276 \\ return !c;
12771277 \\}
12781278 ,
1279 \\pub fn foo(a: c_int, b: f32, c: [*c]c_void) c_int {
1279 \\pub fn foo(a: c_int, b: f32, c: ?*c_void) c_int {
12801280 \\ return !(a == 0);
12811281 \\ return !(a != 0);
12821282 \\ return !(b != 0);
......@@ -1334,7 +1334,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
13341334 \\ B,
13351335 \\ C,
13361336 \\};
1337 \\pub fn if_none_bool(a: c_int, b: f32, c: [*c]c_void, d: enum_SomeEnum) c_int {
1337 \\pub fn if_none_bool(a: c_int, b: f32, c: ?*c_void, d: enum_SomeEnum) c_int {
13381338 \\ if (a != 0) return 0;
13391339 \\ if (b != 0) return 1;
13401340 \\ if (c != 0) return 2;
......@@ -1351,7 +1351,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
13511351 \\ return 3;
13521352 \\}
13531353 ,
1354 \\pub fn while_none_bool(a: c_int, b: f32, c: [*c]c_void) c_int {
1354 \\pub fn while_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
13551355 \\ while (a != 0) return 0;
13561356 \\ while (b != 0) return 1;
13571357 \\ while (c != 0) return 2;
......@@ -1367,7 +1367,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
13671367 \\ return 3;
13681368 \\}
13691369 ,
1370 \\pub fn for_none_bool(a: c_int, b: f32, c: [*c]c_void) c_int {
1370 \\pub fn for_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
13711371 \\ while (a != 0) return 0;
13721372 \\ while (b != 0) return 1;
13731373 \\ while (c != 0) return 2;