translate-c: back to *c_void for opaque types

See #1059
This commit is contained in:
Andrew Kelley 2019-02-14 23:09:12 -05:00
parent d5bbd74871
commit d6e0d82c32
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
5 changed files with 62 additions and 17 deletions

View File

@ -437,7 +437,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
// move this to a parameter
bool allow_zero = (ptr_len == PtrLenC);
assert(!type_is_invalid(child_type));
assert(ptr_len != PtrLenUnknown || child_type->id != ZigTypeIdOpaque);
assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque);
if (byte_alignment != 0) {
uint32_t abi_alignment = get_abi_alignment(g, child_type);

View File

@ -21205,10 +21205,15 @@ 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;
} else if (instruction->ptr_len == PtrLenC) {
if (!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;
} else if (child_type->id == ZigTypeIdOpaque) {
ir_add_error(ira, &instruction->base, buf_sprintf("C pointers cannot point opaque types"));
return ira->codegen->invalid_instruction;
}
}
uint32_t align_bytes;

View File

@ -763,6 +763,30 @@ static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) {
}
}
static bool type_is_opaque(Context *c, const Type *ty, const SourceLocation &source_loc) {
switch (ty->getTypeClass()) {
case Type::Builtin: {
const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty);
return builtin_ty->getKind() == BuiltinType::Void;
}
case Type::Record: {
const RecordType *record_ty = static_cast<const RecordType*>(ty);
return record_ty->getDecl()->getDefinition() == nullptr;
}
case Type::Elaborated: {
const ElaboratedType *elaborated_ty = static_cast<const ElaboratedType*>(ty);
return type_is_opaque(c, elaborated_ty->getNamedType().getTypePtr(), source_loc);
}
case Type::Typedef: {
const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty);
const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
return type_is_opaque(c, typedef_decl->getUnderlyingType().getTypePtr(), source_loc);
}
default:
return false;
}
}
static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &source_loc) {
switch (ty->getTypeClass()) {
case Type::Builtin:
@ -912,8 +936,14 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
return trans_create_node_prefix_op(c, PrefixOpOptional, child_node);
}
return trans_create_node_ptr_type(c, child_qt.isConstQualified(),
child_qt.isVolatileQualified(), child_node, PtrLenC);
if (type_is_opaque(c, child_qt.getTypePtr(), source_loc)) {
AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(),
child_qt.isVolatileQualified(), child_node, PtrLenSingle);
return trans_create_node_prefix_op(c, PrefixOpOptional, pointer_node);
} else {
return trans_create_node_ptr_type(c, child_qt.isConstQualified(),
child_qt.isVolatileQualified(), child_node, PtrLenC);
}
}
case Type::Typedef:
{

View File

@ -1,6 +1,16 @@
const tests = @import("tests.zig");
pub fn addCases(cases: *tests.CompileErrorContext) void {
cases.addTest(
"C pointer to c_void",
\\export fn a() void {
\\ var x: *c_void = undefined;
\\ var y: [*c]c_void = x;
\\}
,
".tmp_source.zig:3:12: error: C pointers cannot point opaque types",
);
cases.addTest(
"directly embedding opaque type in struct and union",
\\const O = @OpaqueType();

View File

@ -202,7 +202,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
cases.add("restrict -> noalias",
\\void foo(void *restrict bar, void *restrict);
,
\\pub extern fn foo(noalias bar: [*c]c_void, noalias arg1: [*c]c_void) void;
\\pub extern fn foo(noalias bar: ?*c_void, noalias arg1: ?*c_void) void;
);
cases.add("simple struct",
@ -275,7 +275,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
,
\\pub const struct_Foo = @OpaqueType();
,
\\pub extern fn some_func(foo: [*c]struct_Foo, x: c_int) [*c]struct_Foo;
\\pub extern fn some_func(foo: ?*struct_Foo, x: c_int) ?*struct_Foo;
,
\\pub const Foo = struct_Foo;
);
@ -336,7 +336,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
,
\\pub const Foo = c_void;
,
\\pub extern fn fun(a: [*c]Foo) Foo;
\\pub extern fn fun(a: ?*Foo) Foo;
);
cases.add("generate inline func for #define global extern fn",
@ -608,7 +608,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ return 6;
\\}
,
\\pub export fn and_or_none_bool(a: c_int, b: f32, c: [*c]c_void) c_int {
\\pub export fn and_or_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
\\ if ((a != 0) and (b != 0)) return 0;
\\ if ((b != 0) and (c != 0)) return 1;
\\ if ((a != 0) and (c != 0)) return 2;
@ -756,8 +756,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ return x;
\\}
,
\\pub export fn foo(x: [*c]c_ushort) [*c]c_void {
\\ return @ptrCast([*c]c_void, x);
\\pub export fn foo(x: [*c]c_ushort) ?*c_void {
\\ return @ptrCast(?*c_void, x);
\\}
);
@ -1276,7 +1276,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ return !c;
\\}
,
\\pub fn foo(a: c_int, b: f32, c: [*c]c_void) c_int {
\\pub fn foo(a: c_int, b: f32, c: ?*c_void) c_int {
\\ return !(a == 0);
\\ return !(a != 0);
\\ return !(b != 0);
@ -1334,7 +1334,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ B,
\\ C,
\\};
\\pub fn if_none_bool(a: c_int, b: f32, c: [*c]c_void, d: enum_SomeEnum) c_int {
\\pub fn if_none_bool(a: c_int, b: f32, c: ?*c_void, d: enum_SomeEnum) c_int {
\\ if (a != 0) return 0;
\\ if (b != 0) return 1;
\\ if (c != 0) return 2;
@ -1351,7 +1351,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ return 3;
\\}
,
\\pub fn while_none_bool(a: c_int, b: f32, c: [*c]c_void) c_int {
\\pub fn while_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
\\ while (a != 0) return 0;
\\ while (b != 0) return 1;
\\ while (c != 0) return 2;
@ -1367,7 +1367,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ return 3;
\\}
,
\\pub fn for_none_bool(a: c_int, b: f32, c: [*c]c_void) c_int {
\\pub fn for_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
\\ while (a != 0) return 0;
\\ while (b != 0) return 1;
\\ while (c != 0) return 2;