From 36b4658752257a27b1d7db5a4396132784801997 Mon Sep 17 00:00:00 2001 From: TwoClocks <5883156+TwoClocks@users.noreply.github.com> Date: Fri, 31 Dec 2021 13:01:14 -0800 Subject: [PATCH 1/2] translate-c: check record fields for opaque demotions --- src/translate_c.zig | 11 ++++++++++- test/translate_c.zig | 24 ++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/translate_c.zig b/src/translate_c.zig index 8c4bd5e9bf..06ccf53f63 100644 --- a/src/translate_c.zig +++ b/src/translate_c.zig @@ -4831,7 +4831,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); diff --git a/test/translate_c.zig b/test/translate_c.zig index c49aa55baa..590e52f2ae 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -3607,6 +3607,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); From 0274e2f1fd3b7a81344080d532cfd2d384427cd2 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Fri, 27 May 2022 16:43:21 +0300 Subject: [PATCH 2/2] translate-c: check variable types being demoted to opaque --- src/translate_c.zig | 9 +++++++-- test/translate_c.zig | 16 +++++++++++++++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/translate_c.zig b/src/translate_c.zig index 06ccf53f63..3bbe1e6f46 100644 --- a/src/translate_c.zig +++ b/src/translate_c.zig @@ -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| diff --git a/test/translate_c.zig b/test/translate_c.zig index 590e52f2ae..f5748f0659 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -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;