mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 04:48:20 +00:00
Merge pull request #10474 from TwoClocks/master
translate-c: fix for #10461. Check child records for opaque types
This commit is contained in:
commit
f846dc420f
@ -793,6 +793,10 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co
|
||||
var is_extern = storage_class == .Extern and !has_init;
|
||||
var is_export = !is_extern and storage_class != .Static;
|
||||
|
||||
if (!is_extern and qualTypeWasDemotedToOpaque(c, qual_type)) {
|
||||
return failDecl(c, var_decl_loc, var_name, "non-extern variable has opaque type", .{});
|
||||
}
|
||||
|
||||
const type_node = transQualTypeMaybeInitialized(c, scope, qual_type, decl_init, var_decl_loc) catch |err| switch (err) {
|
||||
error.UnsupportedTranslation, error.UnsupportedType => {
|
||||
return failDecl(c, var_decl_loc, var_name, "unable to resolve variable type", .{});
|
||||
@ -1839,6 +1843,7 @@ fn transDeclStmtOne(
|
||||
.Var => {
|
||||
const var_decl = @ptrCast(*const clang.VarDecl, decl);
|
||||
const decl_init = var_decl.getInit();
|
||||
const loc = decl.getLocation();
|
||||
|
||||
const qual_type = var_decl.getTypeSourceInfo_getType();
|
||||
const name = try c.str(@ptrCast(*const clang.NamedDecl, var_decl).getName_bytes_begin());
|
||||
@ -1848,12 +1853,12 @@ fn transDeclStmtOne(
|
||||
// This is actually a global variable, put it in the global scope and reference it.
|
||||
// `_ = mangled_name;`
|
||||
return visitVarDecl(c, var_decl, mangled_name);
|
||||
} else if (qualTypeWasDemotedToOpaque(c, qual_type)) {
|
||||
return fail(c, error.UnsupportedTranslation, loc, "local variable has opaque type", .{});
|
||||
}
|
||||
|
||||
const is_static_local = var_decl.isStaticLocal();
|
||||
const is_const = qual_type.isConstQualified();
|
||||
|
||||
const loc = decl.getLocation();
|
||||
const type_node = try transQualTypeMaybeInitialized(c, scope, qual_type, decl_init, loc);
|
||||
|
||||
var init_node = if (decl_init) |expr|
|
||||
@ -4831,7 +4836,16 @@ fn qualTypeWasDemotedToOpaque(c: *Context, qt: clang.QualType) bool {
|
||||
|
||||
const record_decl = record_ty.getDecl();
|
||||
const canonical = @ptrToInt(record_decl.getCanonicalDecl());
|
||||
return c.opaque_demotes.contains(canonical);
|
||||
if (c.opaque_demotes.contains(canonical)) return true;
|
||||
|
||||
// check all childern for opaque types.
|
||||
var it = record_decl.field_begin();
|
||||
const end_it = record_decl.field_end();
|
||||
while (it.neq(end_it)) : (it = it.next()) {
|
||||
const field_decl = it.deref();
|
||||
if (qualTypeWasDemotedToOpaque(c, field_decl.getType())) return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
.Enum => {
|
||||
const enum_ty = @ptrCast(*const clang.EnumType, ty);
|
||||
|
||||
@ -6,6 +6,20 @@ const CrossTarget = std.zig.CrossTarget;
|
||||
pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
const default_enum_type = if (builtin.abi == .msvc) "c_int" else "c_uint";
|
||||
|
||||
cases.add("variables check for opaque demotion",
|
||||
\\struct A {
|
||||
\\ _Atomic int a;
|
||||
\\} a;
|
||||
\\int main(void) {
|
||||
\\ struct A a;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub const struct_A = opaque {};
|
||||
\\pub const a = @compileError("non-extern variable has opaque type");
|
||||
,
|
||||
\\pub extern fn main() c_int;
|
||||
});
|
||||
|
||||
cases.add("field access is grouped if necessary",
|
||||
\\unsigned long foo(unsigned long x) {
|
||||
\\ return ((union{unsigned long _x}){x})._x;
|
||||
@ -3587,7 +3601,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ struct my_struct S = {.a = 1, .b = 2};
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\warning: cannot initialize opaque type
|
||||
\\warning: local variable has opaque type
|
||||
,
|
||||
\\warning: unable to translate function, demoted to extern
|
||||
\\pub extern fn initialize() void;
|
||||
@ -3607,6 +3621,30 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\pub extern fn deref(arg_s: ?*struct_my_struct) void;
|
||||
});
|
||||
|
||||
cases.add("Demote function that dereference types that contain opaque type",
|
||||
\\struct inner {
|
||||
\\ _Atomic int a;
|
||||
\\};
|
||||
\\struct outer {
|
||||
\\ int thing;
|
||||
\\ struct inner sub_struct;
|
||||
\\};
|
||||
\\void deref(struct outer *s) {
|
||||
\\ *s;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub const struct_inner = opaque {};
|
||||
,
|
||||
\\pub const struct_outer = extern struct {
|
||||
\\ thing: c_int,
|
||||
\\ sub_struct: struct_inner,
|
||||
\\};
|
||||
,
|
||||
\\warning: unable to translate function, demoted to extern
|
||||
,
|
||||
\\pub extern fn deref(arg_s: ?*struct_outer) void;
|
||||
});
|
||||
|
||||
cases.add("Function prototype declared within function",
|
||||
\\int foo(void) {
|
||||
\\ extern int bar(int, int);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user