From c0489abcdbad82c95e332e5c7f9982b368a441f0 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 13 Jul 2019 12:38:10 -0400 Subject: [PATCH] translate-c: fix incorrectly translated double function pointer closes #2887 --- src/translate_c.cpp | 25 ++++++++++++++++++++++++- test/translate_c.zig | 14 ++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/translate_c.cpp b/src/translate_c.cpp index 1487db0ff..69c70958e 100644 --- a/src/translate_c.cpp +++ b/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(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(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), diff --git a/test/translate_c.zig b/test/translate_c.zig index 48dac1e12..f25d708f3 100644 --- a/test/translate_c.zig +++ b/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;