Skip to content

Commit d6e0d82

Browse files
committed
translate-c: back to *c_void for opaque types
See #1059
1 parent d5bbd74 commit d6e0d82

File tree

5 files changed

+62
-17
lines changed

5 files changed

+62
-17
lines changed

src/analyze.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,30 @@ static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) {
763763
}
764764
}
765765

766+
static 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+
766790
static 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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
const tests = @import("tests.zig");
22

33
pub 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

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -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;

0 commit comments

Comments
 (0)