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