| ... | ... | @@ -575,12 +575,14 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void { |
| 575 | 575 | const fn_decl_loc = fn_decl.getLocation(); |
| 576 | 576 | const has_body = fn_decl.hasBody(); |
| 577 | 577 | const storage_class = fn_decl.getStorageClass(); |
| 578 | const is_always_inline = has_body and fn_decl.hasAlwaysInlineAttr(); |
| 578 | 579 | var decl_ctx = FnDeclContext{ |
| 579 | 580 | .fn_name = fn_name, |
| 580 | 581 | .has_body = has_body, |
| 581 | 582 | .storage_class = storage_class, |
| 583 | .is_always_inline = is_always_inline, |
| 582 | 584 | .is_export = switch (storage_class) { |
| 583 | | .None => has_body and !fn_decl.isInlineSpecified(), |
| 585 | .None => has_body and !is_always_inline and !fn_decl.isInlineSpecified(), |
| 584 | 586 | .Extern, .Static => false, |
| 585 | 587 | .PrivateExtern => return failDecl(c, fn_decl_loc, fn_name, "unsupported storage class: private extern", .{}), |
| 586 | 588 | .Auto => unreachable, // Not legal on functions |
| ... | ... | @@ -615,6 +617,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void { |
| 615 | 617 | decl_ctx.has_body = false; |
| 616 | 618 | decl_ctx.storage_class = .Extern; |
| 617 | 619 | decl_ctx.is_export = false; |
| 620 | decl_ctx.is_always_inline = false; |
| 618 | 621 | try warn(c, &c.global_scope.base, fn_decl_loc, "TODO unable to translate variadic function, demoted to extern", .{}); |
| 619 | 622 | } |
| 620 | 623 | break :blk transFnProto(c, fn_decl, fn_proto_type, fn_decl_loc, decl_ctx, true) catch |err| switch (err) { |
| ... | ... | @@ -653,6 +656,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void { |
| 653 | 656 | const param_name = param.name orelse { |
| 654 | 657 | proto_node.data.is_extern = true; |
| 655 | 658 | proto_node.data.is_export = false; |
| 659 | proto_node.data.is_inline = false; |
| 656 | 660 | try warn(c, &c.global_scope.base, fn_decl_loc, "function {s} parameter has no name, demoted to extern", .{fn_name}); |
| 657 | 661 | return addTopLevelDecl(c, fn_name, Node.initPayload(&proto_node.base)); |
| 658 | 662 | }; |
| ... | ... | @@ -685,6 +689,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void { |
| 685 | 689 | => { |
| 686 | 690 | proto_node.data.is_extern = true; |
| 687 | 691 | proto_node.data.is_export = false; |
| 692 | proto_node.data.is_inline = false; |
| 688 | 693 | try warn(c, &c.global_scope.base, fn_decl_loc, "unable to translate function, demoted to extern", .{}); |
| 689 | 694 | return addTopLevelDecl(c, fn_name, Node.initPayload(&proto_node.base)); |
| 690 | 695 | }, |
| ... | ... | @@ -704,6 +709,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void { |
| 704 | 709 | => { |
| 705 | 710 | proto_node.data.is_extern = true; |
| 706 | 711 | proto_node.data.is_export = false; |
| 712 | proto_node.data.is_inline = false; |
| 707 | 713 | try warn(c, &c.global_scope.base, fn_decl_loc, "unable to create a return value for function, demoted to extern", .{}); |
| 708 | 714 | return addTopLevelDecl(c, fn_name, Node.initPayload(&proto_node.base)); |
| 709 | 715 | }, |
| ... | ... | @@ -974,6 +980,7 @@ fn buildFlexibleArrayFn( |
| 974 | 980 | .is_pub = true, |
| 975 | 981 | .is_extern = false, |
| 976 | 982 | .is_export = false, |
| 983 | .is_inline = false, |
| 977 | 984 | .is_var_args = false, |
| 978 | 985 | .name = field_name, |
| 979 | 986 | .linksection_string = null, |
| ... | ... | @@ -4821,6 +4828,7 @@ const FnDeclContext = struct { |
| 4821 | 4828 | fn_name: []const u8, |
| 4822 | 4829 | has_body: bool, |
| 4823 | 4830 | storage_class: clang.StorageClass, |
| 4831 | is_always_inline: bool, |
| 4824 | 4832 | is_export: bool, |
| 4825 | 4833 | }; |
| 4826 | 4834 | |
| ... | ... | @@ -4871,7 +4879,7 @@ fn transFnNoProto( |
| 4871 | 4879 | is_pub: bool, |
| 4872 | 4880 | ) !*ast.Payload.Func { |
| 4873 | 4881 | const cc = try transCC(c, fn_ty, source_loc); |
| 4874 | | const is_var_args = if (fn_decl_context) |ctx| (!ctx.is_export and ctx.storage_class != .Static) else true; |
| 4882 | const is_var_args = if (fn_decl_context) |ctx| (!ctx.is_export and ctx.storage_class != .Static and !ctx.is_always_inline) else true; |
| 4875 | 4883 | return finishTransFnProto(c, null, null, fn_ty, source_loc, fn_decl_context, is_var_args, cc, is_pub); |
| 4876 | 4884 | } |
| 4877 | 4885 | |
| ... | ... | @@ -4888,9 +4896,9 @@ fn finishTransFnProto( |
| 4888 | 4896 | ) !*ast.Payload.Func { |
| 4889 | 4897 | const is_export = if (fn_decl_context) |ctx| ctx.is_export else false; |
| 4890 | 4898 | const is_extern = if (fn_decl_context) |ctx| !ctx.has_body else false; |
| 4899 | const is_inline = if (fn_decl_context) |ctx| ctx.is_always_inline else false; |
| 4891 | 4900 | const scope = &c.global_scope.base; |
| 4892 | 4901 | |
| 4893 | | // TODO check for always_inline attribute |
| 4894 | 4902 | // TODO check for align attribute |
| 4895 | 4903 | |
| 4896 | 4904 | var fn_params = std.ArrayList(ast.Payload.Param).init(c.gpa); |
| ... | ... | @@ -4934,7 +4942,7 @@ fn finishTransFnProto( |
| 4934 | 4942 | |
| 4935 | 4943 | const alignment = if (fn_decl) |decl| zigAlignment(decl.getAlignedAttribute(c.clang_context)) else null; |
| 4936 | 4944 | |
| 4937 | | const explicit_callconv = if ((is_export or is_extern) and cc == .C) null else cc; |
| 4945 | const explicit_callconv = if ((is_inline or is_export or is_extern) and cc == .C) null else cc; |
| 4938 | 4946 | |
| 4939 | 4947 | const return_type_node = blk: { |
| 4940 | 4948 | if (fn_ty.getNoReturnAttr()) { |
| ... | ... | @@ -4963,6 +4971,7 @@ fn finishTransFnProto( |
| 4963 | 4971 | .is_pub = is_pub, |
| 4964 | 4972 | .is_extern = is_extern, |
| 4965 | 4973 | .is_export = is_export, |
| 4974 | .is_inline = is_inline, |
| 4966 | 4975 | .is_var_args = is_var_args, |
| 4967 | 4976 | .name = name, |
| 4968 | 4977 | .linksection_string = linksection_string, |