Commit 4613e4d15f

Rocknest <35231115+Rocknest@users.noreply.github.com>
2020-01-09 19:38:31
Fix C struct with function pointer member and typedefs mistranslated (#4122)
fixes #4118
1 parent 834218d
Changed files (2)
src-self-hosted/translate_c.zig
@@ -392,7 +392,7 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void {
             return visitFnDecl(c, @ptrCast(*const ZigClangFunctionDecl, decl));
         },
         .Typedef => {
-            _ = try transTypeDef(c, @ptrCast(*const ZigClangTypedefNameDecl, decl));
+            _ = try transTypeDef(c, @ptrCast(*const ZigClangTypedefNameDecl, decl), true);
         },
         .Enum => {
             _ = try transEnumDecl(c, @ptrCast(*const ZigClangEnumDecl, decl));
@@ -636,9 +636,9 @@ fn transTypeDefAsBuiltin(c: *Context, typedef_decl: *const ZigClangTypedefNameDe
     return transCreateNodeIdentifier(c, builtin_name);
 }
 
-fn transTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Error!?*ast.Node {
+fn transTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl, top_level_visit: bool) Error!?*ast.Node {
     if (c.decl_table.get(@ptrToInt(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl)))) |kv|
-        return try transCreateNodeIdentifier(c, kv.value); // Avoid processing this decl twice
+        return transCreateNodeIdentifier(c, kv.value); // Avoid processing this decl twice
     const rp = makeRestorePoint(c);
 
     const typedef_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, typedef_decl)));
@@ -671,6 +671,10 @@ fn transTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Error
         return transTypeDefAsBuiltin(c, typedef_decl, "isize")
     else if (mem.eql(u8, checked_name, "size_t"))
         return transTypeDefAsBuiltin(c, typedef_decl, "usize");
+    
+    if (!top_level_visit) {
+        return transCreateNodeIdentifier(c, checked_name);
+    }
 
     _ = try c.decl_table.put(@ptrToInt(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl)), checked_name);
     const visib_tok = try appendToken(c, .Keyword_pub, "pub");
@@ -4299,7 +4303,7 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
             const typedef_ty = @ptrCast(*const ZigClangTypedefType, ty);
 
             const typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
-            return (try transTypeDef(rp.c, typedef_decl)) orelse
+            return (try transTypeDef(rp.c, typedef_decl, false)) orelse
                 revertAndWarn(rp, error.UnsupportedType, source_loc, "unable to translate typedef declaration", .{});
         },
         .Record => {
test/run_translated_c.zig
@@ -3,6 +3,22 @@ const tests = @import("tests.zig");
 const nl = std.cstr.line_sep;
 
 pub fn addCases(cases: *tests.RunTranslatedCContext) void {
+    cases.add("typedef and function pointer",
+        \\#include <stdlib.h>
+        \\typedef struct _Foo Foo;
+        \\typedef int Ret;
+        \\typedef int Param;
+        \\struct _Foo { Ret (*func)(Param p); };
+        \\static Ret add1(Param p) {
+        \\    return p + 1;
+        \\}
+        \\int main(int argc, char **argv) {
+        \\    Foo strct = { .func = add1 };
+        \\    if (strct.func(16) != 17) abort();
+        \\    return 0;
+        \\}
+    , "");
+    
     cases.add("ternary operator",
         \\#include <stdlib.h>
         \\static int cnt = 0;