Commit 36b4658752

TwoClocks <5883156+TwoClocks@users.noreply.github.com>
2021-12-31 22:01:14
translate-c: check record fields for opaque demotions
1 parent ee651c3
Changed files (2)
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);
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);