Commit c0489abcdb

Andrew Kelley <andrew@ziglang.org>
2019-07-13 18:38:10
translate-c: fix incorrectly translated double function pointer
closes #2887
1 parent bdfb314
Changed files (2)
src/translate_c.cpp
@@ -833,6 +833,27 @@ static bool qual_type_has_wrapping_overflow(Context *c, ZigClangQualType qt) {
     }
 }
 
+static bool type_is_function(Context *c, const ZigClangType *ty, ZigClangSourceLocation source_loc) {
+    switch (ZigClangType_getTypeClass(ty)) {
+        case ZigClangType_FunctionProto:
+        case ZigClangType_FunctionNoProto:
+            return true;
+        case ZigClangType_Elaborated: {
+            const clang::ElaboratedType *elaborated_ty = reinterpret_cast<const clang::ElaboratedType*>(ty);
+            ZigClangQualType qt = bitcast(elaborated_ty->getNamedType());
+            return type_is_function(c, ZigClangQualType_getTypePtr(qt), source_loc);
+        }
+        case ZigClangType_Typedef: {
+            const ZigClangTypedefType *typedef_ty = reinterpret_cast<const ZigClangTypedefType*>(ty);
+            const ZigClangTypedefNameDecl *typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
+            ZigClangQualType underlying_type = ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl);
+            return type_is_function(c, ZigClangQualType_getTypePtr(underlying_type), source_loc);
+        }
+        default:
+            return false;
+    }
+}
+
 static bool type_is_opaque(Context *c, const ZigClangType *ty, ZigClangSourceLocation source_loc) {
     switch (ZigClangType_getTypeClass(ty)) {
         case ZigClangType_Builtin: {
@@ -1034,7 +1055,9 @@ static AstNode *trans_type(Context *c, const ZigClangType *ty, ZigClangSourceLoc
                     return trans_create_node_prefix_op(c, PrefixOpOptional, child_node);
                 }
 
-                if (type_is_opaque(c, ZigClangQualType_getTypePtr(child_qt), source_loc)) {
+                if (type_is_function(c, ZigClangQualType_getTypePtr(child_qt), source_loc)) {
+                    return trans_create_node_prefix_op(c, PrefixOpOptional, child_node);
+                } else if (type_is_opaque(c, ZigClangQualType_getTypePtr(child_qt), source_loc)) {
                     AstNode *pointer_node = trans_create_node_ptr_type(c,
                             ZigClangQualType_isConstQualified(child_qt),
                             ZigClangQualType_isVolatileQualified(child_qt),
test/translate_c.zig
@@ -40,6 +40,20 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
     );
 
     /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
+    cases.add("typedef of function in struct field",
+        \\typedef void lws_callback_function(void);
+        \\struct Foo {
+        \\    void (*func)(void);
+        \\    lws_callback_function *callback_http;
+        \\};
+    ,
+        \\pub const lws_callback_function = extern fn() void;
+        \\pub const struct_Foo = extern struct {
+        \\    func: ?extern fn() void,
+        \\    callback_http: ?lws_callback_function,
+        \\};
+    );
+
     cases.add("pointer to struct demoted to opaque due to bit fields",
         \\struct Foo {
         \\    unsigned int: 1;