| ... | ... | @@ -271,7 +271,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { |
| 271 | 271 | const proto_node = switch (ZigClangType_getTypeClass(fn_type)) { |
| 272 | 272 | .FunctionProto => blk: { |
| 273 | 273 | const fn_proto_type = @ptrCast(*const ZigClangFunctionProtoType, fn_type); |
| 274 | | break :blk transFnProto(rp, fn_proto_type, fn_decl_loc, decl_ctx) catch |err| switch (err) { |
| 274 | break :blk transFnProto(rp, fn_proto_type, fn_decl_loc, decl_ctx, true) catch |err| switch (err) { |
| 275 | 275 | error.UnsupportedType => { |
| 276 | 276 | return failDecl(c, fn_decl_loc, fn_name, "unable to resolve prototype of function"); |
| 277 | 277 | }, |
| ... | ... | @@ -280,7 +280,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { |
| 280 | 280 | }, |
| 281 | 281 | .FunctionNoProto => blk: { |
| 282 | 282 | const fn_no_proto_type = @ptrCast(*const ZigClangFunctionType, fn_type); |
| 283 | | break :blk transFnNoProto(rp, fn_no_proto_type, fn_decl_loc, decl_ctx) catch |err| switch (err) { |
| 283 | break :blk transFnNoProto(rp, fn_no_proto_type, fn_decl_loc, decl_ctx, true) catch |err| switch (err) { |
| 284 | 284 | error.UnsupportedType => { |
| 285 | 285 | return failDecl(c, fn_decl_loc, fn_name, "unable to resolve prototype of function"); |
| 286 | 286 | }, |
| ... | ... | @@ -420,7 +420,6 @@ fn transCompoundStmtInline( |
| 420 | 420 | while (it != end_it) : (it += 1) { |
| 421 | 421 | const result = try transStmt(rp, parent_scope, it.*, .unused, .r_value); |
| 422 | 422 | scope = result.child_scope; |
| 423 | | std.debug.warn("id: {}\n", result.node.id); |
| 424 | 423 | if (result.node != &block_node.base) |
| 425 | 424 | try block_node.statements.push(result.node); |
| 426 | 425 | } |
| ... | ... | @@ -661,10 +660,13 @@ fn transCCast( |
| 661 | 660 | if (qualTypeIsPtr(dst_type) and qualTypeIsPtr(src_type)) |
| 662 | 661 | return transCPtrCast(rp, loc, dst_type, src_type, expr); |
| 663 | 662 | if (cIsUnsignedInteger(dst_type) and qualTypeIsPtr(src_type)) { |
| 663 | const cast_node = try transCreateNodeFnCall(rp.c, try transQualType(rp, dst_type, loc)); |
| 664 | 664 | const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "@ptrToInt"); |
| 665 | 665 | try builtin_node.params.push(expr); |
| 666 | 666 | builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| 667 | | return &(try transCreateNodeFnCall(rp.c, try transQualType(rp, dst_type, loc), &builtin_node.base)).base; |
| 667 | try cast_node.op.Call.params.push(&builtin_node.base); |
| 668 | cast_node.rtoken = try appendToken(rp.c, .RParen, ")"); |
| 669 | return &cast_node.base; |
| 668 | 670 | } |
| 669 | 671 | if (cIsUnsignedInteger(src_type) and qualTypeIsPtr(dst_type)) { |
| 670 | 672 | const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "@intToPtr"); |
| ... | ... | @@ -677,7 +679,10 @@ fn transCCast( |
| 677 | 679 | // TODO: maybe widen to increase size |
| 678 | 680 | // TODO: maybe bitcast to change sign |
| 679 | 681 | // TODO: maybe truncate to reduce size |
| 680 | | return &(try transCreateNodeFnCall(rp.c, try transQualType(rp, dst_type, loc), expr)).base; |
| 682 | const cast_node = try transCreateNodeFnCall(rp.c, try transQualType(rp, dst_type, loc)); |
| 683 | try cast_node.op.Call.params.push(expr); |
| 684 | cast_node.rtoken = try appendToken(rp.c, .RParen, ")"); |
| 685 | return &cast_node.base; |
| 681 | 686 | } |
| 682 | 687 | |
| 683 | 688 | fn transExpr( |
| ... | ... | @@ -728,13 +733,15 @@ fn transCPtrCast( |
| 728 | 733 | // void has 1-byte alignment, so @alignCast is not needed |
| 729 | 734 | try ptrcast_node.params.push(expr); |
| 730 | 735 | } else { |
| 736 | const aligncast_node = try transCreateNodeBuiltinFnCall(rp.c, "@alignCast"); |
| 731 | 737 | const alignof_node = try transCreateNodeBuiltinFnCall(rp.c, "@alignOf"); |
| 732 | 738 | const child_type_node = try transQualType(rp, child_type, loc); |
| 733 | 739 | try alignof_node.params.push(child_type_node); |
| 734 | | const aligncast_node = try transCreateNodeBuiltinFnCall(rp.c, "@alignCast"); |
| 740 | alignof_node.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| 735 | 741 | try aligncast_node.params.push(&alignof_node.base); |
| 736 | 742 | _ = try appendToken(rp.c, .Comma, ","); |
| 737 | 743 | try aligncast_node.params.push(expr); |
| 744 | aligncast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| 738 | 745 | try ptrcast_node.params.push(&aligncast_node.base); |
| 739 | 746 | } |
| 740 | 747 | ptrcast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| ... | ... | @@ -909,7 +916,7 @@ fn transCreateNodeBuiltinFnCall(c: *Context, name: []const u8) !*ast.Node.Builti |
| 909 | 916 | return node; |
| 910 | 917 | } |
| 911 | 918 | |
| 912 | | fn transCreateNodeFnCall(c: *Context, fn_expr: *ast.Node, first_arg: *ast.Node) !*ast.Node.SuffixOp { |
| 919 | fn transCreateNodeFnCall(c: *Context, fn_expr: *ast.Node) !*ast.Node.SuffixOp { |
| 913 | 920 | _ = try appendToken(c, .LParen, "("); |
| 914 | 921 | const node = try c.a().create(ast.Node.SuffixOp); |
| 915 | 922 | node.* = ast.Node.SuffixOp{ |
| ... | ... | @@ -921,37 +928,34 @@ fn transCreateNodeFnCall(c: *Context, fn_expr: *ast.Node, first_arg: *ast.Node) |
| 921 | 928 | .async_attr = null, |
| 922 | 929 | }, |
| 923 | 930 | }, |
| 924 | | .rtoken = try appendToken(c, .RParen, ")"), |
| 931 | .rtoken = undefined, // set after appending args |
| 925 | 932 | }; |
| 926 | | try node.op.Call.params.push(first_arg); |
| 927 | 933 | return node; |
| 928 | 934 | } |
| 929 | 935 | |
| 930 | 936 | fn transCreateNodePrefixOp( |
| 931 | 937 | c: *Context, |
| 932 | 938 | op: ast.Node.PrefixOp.Op, |
| 933 | | rhs: *ast.Node, |
| 934 | 939 | op_tok_id: std.zig.Token.Id, |
| 935 | 940 | bytes: []const u8, |
| 936 | | ) !*ast.Node { |
| 941 | ) !*ast.Node.PrefixOp { |
| 937 | 942 | const node = try c.a().create(ast.Node.PrefixOp); |
| 938 | 943 | node.* = ast.Node.PrefixOp{ |
| 939 | 944 | .base = ast.Node{ .id = .PrefixOp }, |
| 940 | 945 | .op_token = try appendToken(c, op_tok_id, bytes), |
| 941 | 946 | .op = op, |
| 942 | | .rhs = rhs, |
| 947 | .rhs = undefined, // translate and set afterward |
| 943 | 948 | }; |
| 944 | | return &node.base; |
| 949 | return node; |
| 945 | 950 | } |
| 946 | 951 | |
| 947 | 952 | fn transCreateNodePtrType( |
| 948 | 953 | c: *Context, |
| 949 | 954 | is_const: bool, |
| 950 | 955 | is_volatile: bool, |
| 951 | | rhs: *ast.Node, |
| 952 | 956 | op_tok_id: std.zig.Token.Id, |
| 953 | 957 | bytes: []const u8, |
| 954 | | ) !*ast.Node { |
| 958 | ) !*ast.Node.PrefixOp { |
| 955 | 959 | const node = try c.a().create(ast.Node.PrefixOp); |
| 956 | 960 | node.* = ast.Node.PrefixOp{ |
| 957 | 961 | .base = ast.Node{ .id = .PrefixOp }, |
| ... | ... | @@ -964,9 +968,9 @@ fn transCreateNodePtrType( |
| 964 | 968 | .volatile_token = if (is_volatile) try appendToken(c, .Keyword_volatile, "volatile") else null, |
| 965 | 969 | }, |
| 966 | 970 | }, |
| 967 | | .rhs = rhs, |
| 971 | .rhs = undefined, // translate and set afterward |
| 968 | 972 | }; |
| 969 | | return &node.base; |
| 973 | return node; |
| 970 | 974 | } |
| 971 | 975 | |
| 972 | 976 | fn transCreateNodeAPInt(c: *Context, int: ?*const ZigClangAPSInt) !*ast.Node { |
| ... | ... | @@ -1038,7 +1042,7 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour |
| 1038 | 1042 | }, |
| 1039 | 1043 | .FunctionProto => { |
| 1040 | 1044 | const fn_proto_ty = @ptrCast(*const ZigClangFunctionProtoType, ty); |
| 1041 | | const fn_proto = try transFnProto(rp, fn_proto_ty, source_loc, null); |
| 1045 | const fn_proto = try transFnProto(rp, fn_proto_ty, source_loc, null, false); |
| 1042 | 1046 | return &fn_proto.base; |
| 1043 | 1047 | }, |
| 1044 | 1048 | .Paren => { |
| ... | ... | @@ -1047,28 +1051,33 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour |
| 1047 | 1051 | }, |
| 1048 | 1052 | .Pointer => { |
| 1049 | 1053 | const child_qt = ZigClangType_getPointeeType(ty); |
| 1050 | | const child_node = try transQualType(rp, child_qt, source_loc); |
| 1051 | | if (qualTypeChildIsFnProto(child_qt)) |
| 1052 | | return transCreateNodePrefixOp(rp.c, .OptionalType, child_node, .QuestionMark, "?"); |
| 1054 | if (qualTypeChildIsFnProto(child_qt)) { |
| 1055 | const optional_node = try transCreateNodePrefixOp(rp.c, .OptionalType, .QuestionMark, "?"); |
| 1056 | optional_node.rhs = try transQualType(rp, child_qt, source_loc); |
| 1057 | return &optional_node.base; |
| 1058 | } |
| 1053 | 1059 | if (typeIsOpaque(rp.c, ZigClangQualType_getTypePtr(child_qt), source_loc)) { |
| 1060 | const optional_node = try transCreateNodePrefixOp(rp.c, .OptionalType, .QuestionMark, "?"); |
| 1054 | 1061 | const pointer_node = try transCreateNodePtrType( |
| 1055 | 1062 | rp.c, |
| 1056 | 1063 | ZigClangQualType_isConstQualified(child_qt), |
| 1057 | 1064 | ZigClangQualType_isVolatileQualified(child_qt), |
| 1058 | | child_node, |
| 1059 | 1065 | .Asterisk, |
| 1060 | 1066 | "*", |
| 1061 | 1067 | ); |
| 1062 | | return transCreateNodePrefixOp(rp.c, .OptionalType, pointer_node, .QuestionMark, "?"); |
| 1068 | optional_node.rhs = &pointer_node.base; |
| 1069 | pointer_node.rhs = try transQualType(rp, child_qt, source_loc); |
| 1070 | return &optional_node.base; |
| 1063 | 1071 | } |
| 1064 | | return transCreateNodePtrType( |
| 1072 | const pointer_node = try transCreateNodePtrType( |
| 1065 | 1073 | rp.c, |
| 1066 | 1074 | ZigClangQualType_isConstQualified(child_qt), |
| 1067 | 1075 | ZigClangQualType_isVolatileQualified(child_qt), |
| 1068 | | child_node, |
| 1069 | 1076 | .BracketStarCBracket, |
| 1070 | 1077 | "[*c]", |
| 1071 | 1078 | ); |
| 1079 | pointer_node.rhs = try transQualType(rp, child_qt, source_loc); |
| 1080 | return &pointer_node.base; |
| 1072 | 1081 | }, |
| 1073 | 1082 | else => { |
| 1074 | 1083 | const type_name = rp.c.str(ZigClangType_getTypeClassName(ty)); |
| ... | ... | @@ -1103,6 +1112,7 @@ fn transFnProto( |
| 1103 | 1112 | fn_proto_ty: *const ZigClangFunctionProtoType, |
| 1104 | 1113 | source_loc: ZigClangSourceLocation, |
| 1105 | 1114 | fn_decl_context: ?FnDeclContext, |
| 1115 | is_pub: bool, |
| 1106 | 1116 | ) !*ast.Node.FnProto { |
| 1107 | 1117 | const fn_ty = @ptrCast(*const ZigClangFunctionType, fn_proto_ty); |
| 1108 | 1118 | const cc = try transCC(rp, fn_ty, source_loc); |
| ... | ... | @@ -1113,7 +1123,7 @@ fn transFnProto( |
| 1113 | 1123 | return revertAndWarn(rp, error.UnsupportedType, source_loc, "TODO: implement parameters for FunctionProto in transType"); |
| 1114 | 1124 | } |
| 1115 | 1125 | |
| 1116 | | return finishTransFnProto(rp, fn_ty, source_loc, fn_decl_context, is_var_args, cc); |
| 1126 | return finishTransFnProto(rp, fn_ty, source_loc, fn_decl_context, is_var_args, cc, is_pub); |
| 1117 | 1127 | } |
| 1118 | 1128 | |
| 1119 | 1129 | fn transFnNoProto( |
| ... | ... | @@ -1121,10 +1131,11 @@ fn transFnNoProto( |
| 1121 | 1131 | fn_ty: *const ZigClangFunctionType, |
| 1122 | 1132 | source_loc: ZigClangSourceLocation, |
| 1123 | 1133 | fn_decl_context: ?FnDeclContext, |
| 1134 | is_pub: bool, |
| 1124 | 1135 | ) !*ast.Node.FnProto { |
| 1125 | 1136 | const cc = try transCC(rp, fn_ty, source_loc); |
| 1126 | 1137 | const is_var_args = if (fn_decl_context) |ctx| !ctx.is_export else true; |
| 1127 | | return finishTransFnProto(rp, fn_ty, source_loc, fn_decl_context, is_var_args, cc); |
| 1138 | return finishTransFnProto(rp, fn_ty, source_loc, fn_decl_context, is_var_args, cc, is_pub); |
| 1128 | 1139 | } |
| 1129 | 1140 | |
| 1130 | 1141 | fn finishTransFnProto( |
| ... | ... | @@ -1134,6 +1145,7 @@ fn finishTransFnProto( |
| 1134 | 1145 | fn_decl_context: ?FnDeclContext, |
| 1135 | 1146 | is_var_args: bool, |
| 1136 | 1147 | cc: CallingConvention, |
| 1148 | is_pub: bool, |
| 1137 | 1149 | ) !*ast.Node.FnProto { |
| 1138 | 1150 | const is_export = if (fn_decl_context) |ctx| ctx.is_export else false; |
| 1139 | 1151 | |
| ... | ... | @@ -1141,7 +1153,7 @@ fn finishTransFnProto( |
| 1141 | 1153 | // TODO check for align attribute |
| 1142 | 1154 | |
| 1143 | 1155 | // pub extern fn name(...) T |
| 1144 | | const pub_tok = try appendToken(rp.c, .Keyword_pub, "pub"); |
| 1156 | const pub_tok = if (is_pub) try appendToken(rp.c, .Keyword_pub, "pub") else null; |
| 1145 | 1157 | const cc_tok = if (cc == .Stdcall) try appendToken(rp.c, .Keyword_stdcallcc, "stdcallcc") else null; |
| 1146 | 1158 | const extern_export_inline_tok = if (is_export) |
| 1147 | 1159 | try appendToken(rp.c, .Keyword_export, "export") |