mirror of
https://github.com/ziglang/zig.git
synced 2026-02-20 08:14:48 +00:00
parent
d5bbd74871
commit
d6e0d82c32
@ -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);
|
||||
|
||||
13
src/ir.cpp
13
src/ir.cpp
@ -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;
|
||||
|
||||
@ -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:
|
||||
{
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user