Commit e280dce30f

LemonBoy <LemonBoy@users.noreply.github.com>
2019-02-18 16:26:45
Translate parameterless C functions (#1978)
Both FunctionNoProto and FunctionProto are subclasses of FunctionType, the only difference is that the former is parameterless.
1 parent 7d76264
Changed files (2)
src/translate_c.cpp
@@ -982,11 +982,12 @@ static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::Sourc
                 }
             }
         case clang::Type::FunctionProto:
+        case clang::Type::FunctionNoProto:
             {
-                const clang::FunctionProtoType *fn_proto_ty = static_cast<const clang::FunctionProtoType*>(ty);
+                const clang::FunctionType *fn_ty = static_cast<const clang::FunctionType*>(ty);
 
                 AstNode *proto_node = trans_create_node(c, NodeTypeFnProto);
-                switch (fn_proto_ty->getCallConv()) {
+                switch (fn_ty->getCallConv()) {
                     case clang::CC_C:           // __attribute__((cdecl))
                         proto_node->data.fn_proto.cc = CallingConventionC;
                         proto_node->data.fn_proto.is_extern = true;
@@ -1041,13 +1042,10 @@ static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::Sourc
                         return nullptr;
                 }
 
-                proto_node->data.fn_proto.is_var_args = fn_proto_ty->isVariadic();
-                size_t param_count = fn_proto_ty->getNumParams();
-
-                if (fn_proto_ty->getNoReturnAttr()) {
+                if (fn_ty->getNoReturnAttr()) {
                     proto_node->data.fn_proto.return_type = trans_create_node_symbol_str(c, "noreturn");
                 } else {
-                    proto_node->data.fn_proto.return_type = trans_qual_type(c, fn_proto_ty->getReturnType(),
+                    proto_node->data.fn_proto.return_type = trans_qual_type(c, fn_ty->getReturnType(),
                             source_loc);
                     if (proto_node->data.fn_proto.return_type == nullptr) {
                         emit_warning(c, source_loc, "unsupported function proto return type");
@@ -1070,6 +1068,15 @@ static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::Sourc
                     proto_node->data.fn_proto.name = buf_create_from_str(fn_name);
                 }
 
+                if (ty->getTypeClass() == clang::Type::FunctionNoProto) {
+                    return proto_node;
+                }
+
+                const clang::FunctionProtoType *fn_proto_ty = static_cast<const clang::FunctionProtoType*>(ty);
+
+                proto_node->data.fn_proto.is_var_args = fn_proto_ty->isVariadic();
+                size_t param_count = fn_proto_ty->getNumParams();
+
                 for (size_t i = 0; i < param_count; i += 1) {
                     clang::QualType qt = fn_proto_ty->getParamType(i);
                     AstNode *param_type_node = trans_qual_type(c, qt, source_loc);
@@ -1153,7 +1160,6 @@ static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::Sourc
         case clang::Type::DependentSizedExtVector:
         case clang::Type::Vector:
         case clang::Type::ExtVector:
-        case clang::Type::FunctionNoProto:
         case clang::Type::UnresolvedUsing:
         case clang::Type::Adjusted:
         case clang::Type::TypeOfExpr:
test/translate_c.zig
@@ -1417,6 +1417,14 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\}
     );
 
+    cases.addC("Parameterless function prototypes",
+        \\void foo() {}
+        \\void bar(void) {}
+    ,
+        \\pub export fn foo() void {}
+        \\pub export fn bar() void {}
+    );
+
     // cases.add("empty array with initializer",
     //     "int a[4] = {};"
     // ,