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...@@ -437,7 +437,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
437 // move this to a parameter437 // move this to a parameter
438 bool allow_zero = (ptr_len == PtrLenC);438 bool allow_zero = (ptr_len == PtrLenC);
439 assert(!type_is_invalid(child_type));439 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
442 if (byte_alignment != 0) {442 if (byte_alignment != 0) {
443 uint32_t abi_alignment = get_abi_alignment(g, child_type);443 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...@@ -21205,10 +21205,15 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct
21205 } else if (child_type->id == ZigTypeIdOpaque && instruction->ptr_len == PtrLenUnknown) {21205 } else if (child_type->id == ZigTypeIdOpaque && instruction->ptr_len == PtrLenUnknown) {
21206 ir_add_error(ira, &instruction->base, buf_sprintf("unknown-length pointer to opaque"));21206 ir_add_error(ira, &instruction->base, buf_sprintf("unknown-length pointer to opaque"));
21207 return ira->codegen->invalid_instruction;21207 return ira->codegen->invalid_instruction;
21208 } else if (instruction->ptr_len == PtrLenC && !type_allowed_in_extern(ira->codegen, child_type)) {21208 } else if (instruction->ptr_len == PtrLenC) {
21209 ir_add_error(ira, &instruction->base,21209 if (!type_allowed_in_extern(ira->codegen, child_type)) {
21210 buf_sprintf("C pointers cannot point to non-C-ABI-compatible type '%s'", buf_ptr(&child_type->name)));21210 ir_add_error(ira, &instruction->base,
21211 return ira->codegen->invalid_instruction;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 }
21212 }21217 }
2121321218
21214 uint32_t align_bytes;21219 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) {...@@ -763,6 +763,30 @@ static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) {
763 }763 }
764}764}
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
766static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &source_loc) {790static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &source_loc) {
767 switch (ty->getTypeClass()) {791 switch (ty->getTypeClass()) {
768 case Type::Builtin:792 case Type::Builtin:
...@@ -912,8 +936,14 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou...@@ -912,8 +936,14 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
912 return trans_create_node_prefix_op(c, PrefixOpOptional, child_node);936 return trans_create_node_prefix_op(c, PrefixOpOptional, child_node);
913 }937 }
914938
915 return trans_create_node_ptr_type(c, child_qt.isConstQualified(),939 if (type_is_opaque(c, child_qt.getTypePtr(), source_loc)) {
916 child_qt.isVolatileQualified(), child_node, PtrLenC);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 }
917 }947 }
918 case Type::Typedef:948 case Type::Typedef:
919 {949 {
test/compile_errors.zig+10
...@@ -1,6 +1,16 @@...@@ -1,6 +1,16 @@
1const tests = @import("tests.zig");1const tests = @import("tests.zig");
22
3pub fn addCases(cases: *tests.CompileErrorContext) void {3pub 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
4 cases.addTest(14 cases.addTest(
5 "directly embedding opaque type in struct and union",15 "directly embedding opaque type in struct and union",
6 \\const O = @OpaqueType();16 \\const O = @OpaqueType();
test/translate_c.zig+10-10
...@@ -202,7 +202,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -202,7 +202,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
202 cases.add("restrict -> noalias",202 cases.add("restrict -> noalias",
203 \\void foo(void *restrict bar, void *restrict);203 \\void foo(void *restrict bar, void *restrict);
204 ,204 ,
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;
206 );206 );
207207
208 cases.add("simple struct",208 cases.add("simple struct",
...@@ -275,7 +275,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -275,7 +275,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
275 ,275 ,
276 \\pub const struct_Foo = @OpaqueType();276 \\pub const struct_Foo = @OpaqueType();
277 ,277 ,
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;
279 ,279 ,
280 \\pub const Foo = struct_Foo;280 \\pub const Foo = struct_Foo;
281 );281 );
...@@ -336,7 +336,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -336,7 +336,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
336 ,336 ,
337 \\pub const Foo = c_void;337 \\pub const Foo = c_void;
338 ,338 ,
339 \\pub extern fn fun(a: [*c]Foo) Foo;339 \\pub extern fn fun(a: ?*Foo) Foo;
340 );340 );
341341
342 cases.add("generate inline func for #define global extern fn",342 cases.add("generate inline func for #define global extern fn",
...@@ -608,7 +608,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -608,7 +608,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
608 \\ return 6;608 \\ return 6;
609 \\}609 \\}
610 ,610 ,
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 {
612 \\ if ((a != 0) and (b != 0)) return 0;612 \\ if ((a != 0) and (b != 0)) return 0;
613 \\ if ((b != 0) and (c != 0)) return 1;613 \\ if ((b != 0) and (c != 0)) return 1;
614 \\ if ((a != 0) and (c != 0)) return 2;614 \\ if ((a != 0) and (c != 0)) return 2;
...@@ -756,8 +756,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -756,8 +756,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
756 \\ return x;756 \\ return x;
757 \\}757 \\}
758 ,758 ,
759 \\pub export fn foo(x: [*c]c_ushort) [*c]c_void {759 \\pub export fn foo(x: [*c]c_ushort) ?*c_void {
760 \\ return @ptrCast([*c]c_void, x);760 \\ return @ptrCast(?*c_void, x);
761 \\}761 \\}
762 );762 );
763763
...@@ -1276,7 +1276,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1276,7 +1276,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1276 \\ return !c;1276 \\ return !c;
1277 \\}1277 \\}
1278 ,1278 ,
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 {
1280 \\ return !(a == 0);1280 \\ return !(a == 0);
1281 \\ return !(a != 0);1281 \\ return !(a != 0);
1282 \\ return !(b != 0);1282 \\ return !(b != 0);
...@@ -1334,7 +1334,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1334,7 +1334,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1334 \\ B,1334 \\ B,
1335 \\ C,1335 \\ C,
1336 \\};1336 \\};
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 {
1338 \\ if (a != 0) return 0;1338 \\ if (a != 0) return 0;
1339 \\ if (b != 0) return 1;1339 \\ if (b != 0) return 1;
1340 \\ if (c != 0) return 2;1340 \\ if (c != 0) return 2;
...@@ -1351,7 +1351,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1351,7 +1351,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1351 \\ return 3;1351 \\ return 3;
1352 \\}1352 \\}
1353 ,1353 ,
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 {
1355 \\ while (a != 0) return 0;1355 \\ while (a != 0) return 0;
1356 \\ while (b != 0) return 1;1356 \\ while (b != 0) return 1;
1357 \\ while (c != 0) return 2;1357 \\ while (c != 0) return 2;
...@@ -1367,7 +1367,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1367,7 +1367,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1367 \\ return 3;1367 \\ return 3;
1368 \\}1368 \\}
1369 ,1369 ,
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 {
1371 \\ while (a != 0) return 0;1371 \\ while (a != 0) return 0;
1372 \\ while (b != 0) return 1;1372 \\ while (b != 0) return 1;
1373 \\ while (c != 0) return 2;1373 \\ while (c != 0) return 2;