authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-18 12:47:35+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-18 12:47:35+02:00
logf54e7d6c99b6fbeedcaf91e643e4e3a02e8f1d81
treeb71d135dd5a9ec1e3f06a9e2b64aa38cdbac454b
parent90eed4172d9c4caebe736c2fbf4f9f70c98013c6
signature Commit is signed but in an unrecognized format.

translate-c-2 update @kavika13's work to removal of TransResult


3 files changed, 332 insertions(+), 589 deletions(-)

src-self-hosted/clang.zig+5
...@@ -741,6 +741,11 @@ pub const ZigClangPreprocessedEntity_EntityKind = extern enum {...@@ -741,6 +741,11 @@ pub const ZigClangPreprocessedEntity_EntityKind = extern enum {
741 InclusionDirectiveKind,741 InclusionDirectiveKind,
742};742};
743743
744pub const ZigClangExpr_ConstExprUsage = extern enum {
745 EvaluateForCodeGen,
746 EvaluateForMangling,
747};
748
744pub extern fn ZigClangSourceManager_getSpellingLoc(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) struct_ZigClangSourceLocation;749pub extern fn ZigClangSourceManager_getSpellingLoc(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) struct_ZigClangSourceLocation;
745pub extern fn ZigClangSourceManager_getFilename(self: *const struct_ZigClangSourceManager, SpellingLoc: struct_ZigClangSourceLocation) ?[*:0]const u8;750pub extern fn ZigClangSourceManager_getFilename(self: *const struct_ZigClangSourceManager, SpellingLoc: struct_ZigClangSourceLocation) ?[*:0]const u8;
746pub extern fn ZigClangSourceManager_getSpellingLineNumber(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint;751pub extern fn ZigClangSourceManager_getSpellingLineNumber(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint;
src-self-hosted/translate_c.zig+229-491
...@@ -184,9 +184,7 @@ const Scope = struct {...@@ -184,9 +184,7 @@ const Scope = struct {
184 .Ref => null,184 .Ref => null,
185 .FnDef => @fieldParentPtr(FnDef, "base", scope).getAlias(name),185 .FnDef => @fieldParentPtr(FnDef, "base", scope).getAlias(name),
186 .Block => @fieldParentPtr(Block, "base", scope).getAlias(name),186 .Block => @fieldParentPtr(Block, "base", scope).getAlias(name),
187 .Switch,187 .Switch, .Loop, .Condition => scope.parent.?.getAlias(name),
188 .Loop,
189 .Condition => scope.parent.?.getAlias(name),
190 };188 };
191 }189 }
192190
...@@ -196,9 +194,7 @@ const Scope = struct {...@@ -196,9 +194,7 @@ const Scope = struct {
196 .Root => @fieldParentPtr(Root, "base", scope).contains(name),194 .Root => @fieldParentPtr(Root, "base", scope).contains(name),
197 .FnDef => @fieldParentPtr(FnDef, "base", scope).contains(name),195 .FnDef => @fieldParentPtr(FnDef, "base", scope).contains(name),
198 .Block => @fieldParentPtr(Block, "base", scope).contains(name),196 .Block => @fieldParentPtr(Block, "base", scope).contains(name),
199 .Switch,197 .Switch, .Loop, .Condition => scope.parent.?.contains(name),
200 .Loop,
201 .Condition => scope.parent.?.contains(name),
202 };198 };
203 }199 }
204200
...@@ -594,7 +590,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*...@@ -594,7 +590,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
594 const node = try transCreateNodeVarDecl(c, true, true, name);590 const node = try transCreateNodeVarDecl(c, true, true, name);
595591
596 node.eq_token = try appendToken(c, .Equal, "=");592 node.eq_token = try appendToken(c, .Equal, "=");
597 593
598 var semicolon: ast.TokenIndex = undefined;594 var semicolon: ast.TokenIndex = undefined;
599 node.init_node = blk: {595 node.init_node = blk: {
600 const rp = makeRestorePoint(c);596 const rp = makeRestorePoint(c);
...@@ -634,12 +630,12 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*...@@ -634,12 +630,12 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
634 const field_name = try appendIdentifier(c, try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, field_decl))));630 const field_name = try appendIdentifier(c, try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, field_decl))));
635 _ = try appendToken(c, .Colon, ":");631 _ = try appendToken(c, .Colon, ":");
636 const field_type = transQualType(rp, ZigClangFieldDecl_getType(field_decl), field_loc) catch |err| switch (err) {632 const field_type = transQualType(rp, ZigClangFieldDecl_getType(field_decl), field_loc) catch |err| switch (err) {
637 error.UnsupportedType => {633 error.UnsupportedType => {
638 try failDecl(c, record_loc, name, "unable to translate {} member type", .{container_kind_name});634 try failDecl(c, record_loc, name, "unable to translate {} member type", .{container_kind_name});
639 return null;635 return null;
640 },636 },
641 else => |e| return e,637 else => |e| return e,
642 };638 };
643639
644 const field_node = try c.a().create(ast.Node.ContainerField);640 const field_node = try c.a().create(ast.Node.ContainerField);
645 field_node.* = .{641 field_node.* = .{
...@@ -879,205 +875,166 @@ fn transBinaryOperator(...@@ -879,205 +875,166 @@ fn transBinaryOperator(
879) TransError!*ast.Node {875) TransError!*ast.Node {
880 const op = ZigClangBinaryOperator_getOpcode(stmt);876 const op = ZigClangBinaryOperator_getOpcode(stmt);
881 const qt = ZigClangBinaryOperator_getType(stmt);877 const qt = ZigClangBinaryOperator_getType(stmt);
878 var op_token: ast.TokenIndex = undefined;
879 var op_id: ast.Node.InfixOp.Op = undefined;
882 switch (op) {880 switch (op) {
883 .PtrMemD, .PtrMemI, .Cmp => return revertAndWarn(881 .Assign => return transCreateNodeAssign(rp, scope, result_used, ZigClangBinaryOperator_getLHS(stmt), ZigClangBinaryOperator_getRHS(stmt)),
884 rp,882 .Comma => {
885 error.UnsupportedTranslation,883 const block_scope = try scope.findBlockScope(rp.c);
886 ZigClangBinaryOperator_getBeginLoc(stmt),884 const expr = block_scope.base.parent == scope;
887 "TODO: handle more C binary operators: {}",885 const lparen = if (expr) blk: {
888 .{op},886 const l = try appendToken(rp.c, .LParen, "(");
889 ),887 block_scope.block_node = try transCreateNodeBlock(rp.c, block_scope.label);
890 .Assign => return try transCreateNodeAssign(rp, scope, result_used, ZigClangBinaryOperator_getLHS(stmt), ZigClangBinaryOperator_getRHS(stmt)),888 break :blk l;
891 .Add => {889 } else undefined;
892 const node = if (cIsUnsignedInteger(qt))890
893 try transCreateNodeInfixOp(rp, scope, stmt, .AddWrap, .PlusPercent, "+%", true)891 const lhs = try transExpr(rp, &block_scope.base, ZigClangBinaryOperator_getLHS(stmt), .unused, .r_value);
894 else892 try block_scope.block_node.statements.push(lhs);
895 try transCreateNodeInfixOp(rp, scope, stmt, .Add, .Plus, "+", true);893
896 return maybeSuppressResult(rp, scope, result_used, node);894 const rhs = try transExpr(rp, &block_scope.base, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value);
897 },895 if (expr) {
898 .Sub => {896 _ = try appendToken(rp.c, .Semicolon, ";");
899 const node = if (cIsUnsignedInteger(qt))897 const break_node = try transCreateNodeBreak(rp.c, block_scope.label);
900 try transCreateNodeInfixOp(rp, scope, stmt, .SubWrap, .MinusPercent, "-%", true)898 break_node.rhs = rhs;
901 else899 try block_scope.block_node.statements.push(&break_node.base);
902 try transCreateNodeInfixOp(rp, scope, stmt, .Sub, .Minus, "-", true);900 block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}");
903 return maybeSuppressResult(rp, scope, result_used, node);901 const rparen = try appendToken(rp.c, .RParen, ")");
904 },902 const grouped_expr = try rp.c.a().create(ast.Node.GroupedExpression);
905 .Mul => {903 grouped_expr.* = .{
906 const node = if (cIsUnsignedInteger(qt))904 .lparen = lparen,
907 try transCreateNodeInfixOp(rp, scope, stmt, .MultWrap, .AsteriskPercent, "*%", true)905 .expr = &block_scope.block_node.base,
908 else906 .rparen = rparen,
909 try transCreateNodeInfixOp(rp, scope, stmt, .Mult, .Asterisk, "*", true);907 };
910 return maybeSuppressResult(rp, scope, result_used, node);908 return maybeSuppressResult(rp, scope, result_used, &grouped_expr.base);
909 } else {
910 return maybeSuppressResult(rp, scope, result_used, rhs);
911 }
911 },912 },
912 .Div => {913 .Div => {
913 if (!cIsUnsignedInteger(qt)) {914 if (!cIsUnsignedInteger(qt)) {
914 // signed integer division uses @divTrunc915 // signed integer division uses @divTrunc
915 const div_trunc_node = try transCreateNodeBuiltinFnCall(rp.c, "@divTrunc");916 const div_trunc_node = try transCreateNodeBuiltinFnCall(rp.c, "@divTrunc");
916 const lhs = try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value);917 try div_trunc_node.params.push(try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value));
917 try div_trunc_node.params.push(lhs);
918 _ = try appendToken(rp.c, .Comma, ",");918 _ = try appendToken(rp.c, .Comma, ",");
919 const rhs = try transExpr(rp, scope, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value);919 const rhs = try transExpr(rp, scope, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value);
920 try div_trunc_node.params.push(rhs);920 try div_trunc_node.params.push(rhs);
921 div_trunc_node.rparen_token = try appendToken(rp.c, .RParen, ")");921 div_trunc_node.rparen_token = try appendToken(rp.c, .RParen, ")");
922 return maybeSuppressResult(rp, scope, result_used, &div_trunc_node.base);922 return maybeSuppressResult(rp, scope, result_used, &div_trunc_node.base);
923 } else {
924 // unsigned/float division uses the operator
925 const node = try transCreateNodeInfixOp(rp, scope, stmt, .Div, .Slash, "/", true);
926 return maybeSuppressResult(rp, scope, result_used, node);
927 }923 }
928 },924 },
929 .Rem => {925 .Rem => {
930 if (!cIsUnsignedInteger(qt)) {926 if (!cIsUnsignedInteger(qt)) {
931 // signed integer division uses @rem927 // signed integer division uses @rem
932 const rem_node = try transCreateNodeBuiltinFnCall(rp.c, "@rem");928 const rem_node = try transCreateNodeBuiltinFnCall(rp.c, "@rem");
933 const lhs = try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value);929 try rem_node.params.push(try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value));
934 try rem_node.params.push(lhs);
935 _ = try appendToken(rp.c, .Comma, ",");930 _ = try appendToken(rp.c, .Comma, ",");
936 const rhs = try transExpr(rp, scope, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value);931 const rhs = try transExpr(rp, scope, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value);
937 try rem_node.params.push(rhs);932 try rem_node.params.push(rhs);
938 rem_node.rparen_token = try appendToken(rp.c, .RParen, ")");933 rem_node.rparen_token = try appendToken(rp.c, .RParen, ")");
939 return maybeSuppressResult(rp, scope, result_used, &rem_node.base);934 return maybeSuppressResult(rp, scope, result_used, &rem_node.base);
940 } else {
941 // unsigned/float division uses the operator
942 const node = try transCreateNodeInfixOp(rp, scope, stmt, .Mod, .Percent, "%", true);
943 return maybeSuppressResult(rp, scope, result_used, node);
944 }935 }
945 },936 },
946 .Shl => {937 .Shl => {
947 const node = try transCreateNodeShiftOp(rp, scope, stmt, .BitShiftLeft, .AngleBracketAngleBracketLeft, "<<");938 const node = try transCreateNodeShiftOp(rp, scope, stmt, .BitShiftLeft, .AngleBracketAngleBracketLeft, "<<");
948 return maybeSuppressResult(rp, scope, result_used, TransResult{939 return maybeSuppressResult(rp, scope, result_used, node);
949 .node = node,
950 .child_scope = scope,
951 .node_scope = scope,
952 });
953 },940 },
954 .Shr => {941 .Shr => {
955 const node = try transCreateNodeShiftOp(rp, scope, stmt, .BitShiftRight, .AngleBracketAngleBracketRight, ">>");942 const node = try transCreateNodeShiftOp(rp, scope, stmt, .BitShiftRight, .AngleBracketAngleBracketRight, ">>");
956 return maybeSuppressResult(rp, scope, result_used, TransResult{943 return maybeSuppressResult(rp, scope, result_used, node);
957 .node = node,944 },
958 .child_scope = scope,945 .LAnd => {
959 .node_scope = scope,946 const node = try transCreateNodeBoolInfixOp(rp, scope, stmt, .BoolAnd, result_used, true);
960 });947 return maybeSuppressResult(rp, scope, result_used, node);
948 },
949 .LOr => {
950 const node = try transCreateNodeBoolInfixOp(rp, scope, stmt, .BoolOr, result_used, true);
951 return maybeSuppressResult(rp, scope, result_used, node);
952 },
953 else => {},
954 }
955 const lhs_node = try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value);
956 switch (op) {
957 .PtrMemD, .PtrMemI, .Cmp => return revertAndWarn(
958 rp,
959 error.UnsupportedTranslation,
960 ZigClangBinaryOperator_getBeginLoc(stmt),
961 "TODO: handle more C binary operators: {}",
962 .{op},
963 ),
964 .Add => {
965 if (cIsUnsignedInteger(qt)) {
966 op_token = try appendToken(rp.c, .PlusPercent, "+%");
967 op_id = .AddWrap;
968 } else {
969 op_token = try appendToken(rp.c, .Plus, "+");
970 op_id = .Add;
971 }
972 },
973 .Sub => {
974 if (cIsUnsignedInteger(qt)) {
975 op_token = try appendToken(rp.c, .MinusPercent, "-%");
976 op_id = .SubWrap;
977 } else {
978 op_token = try appendToken(rp.c, .Minus, "-");
979 op_id = .Sub;
980 }
981 },
982 .Mul => {
983 if (cIsUnsignedInteger(qt)) {
984 op_token = try appendToken(rp.c, .AsteriskPercent, "*%");
985 op_id = .MultWrap;
986 } else {
987 op_token = try appendToken(rp.c, .Asterisk, "*");
988 op_id = .Mult;
989 }
990 },
991 .Div => {
992 // unsigned/float division uses the operator
993 op_id = .Div;
994 op_token = try appendToken(rp.c, .Slash, "/");
995 },
996 .Rem => {
997 // unsigned/float division uses the operator
998 op_id = .Mod;
999 op_token = try appendToken(rp.c, .Percent, "%");
961 },1000 },
962 .LT => {1001 .LT => {
963 const node = try transCreateNodeInfixOp(rp, scope, stmt, .LessThan, .AngleBracketLeft, "<", true);1002 op_id = .LessThan;
964 return maybeSuppressResult(rp, scope, result_used, TransResult{1003 op_token = try appendToken(rp.c, .AngleBracketLeft, "<");
965 .node = node,
966 .child_scope = scope,
967 .node_scope = scope,
968 });
969 },1004 },
970 .GT => {1005 .GT => {
971 const node = try transCreateNodeInfixOp(rp, scope, stmt, .GreaterThan, .AngleBracketRight, ">", true);1006 op_id = .GreaterThan;
972 return maybeSuppressResult(rp, scope, result_used, TransResult{1007 op_token = try appendToken(rp.c, .AngleBracketRight, ">");
973 .node = node,
974 .child_scope = scope,
975 .node_scope = scope,
976 });
977 },1008 },
978 .LE => {1009 .LE => {
979 const node = try transCreateNodeInfixOp(rp, scope, stmt, .LessOrEqual, .AngleBracketLeftEqual, "<=", true);1010 op_id = .LessOrEqual;
980 return maybeSuppressResult(rp, scope, result_used, TransResult{1011 op_token = try appendToken(rp.c, .AngleBracketLeftEqual, "<=");
981 .node = node,
982 .child_scope = scope,
983 .node_scope = scope,
984 });
985 },1012 },
986 .GE => {1013 .GE => {
987 const node = try transCreateNodeInfixOp(rp, scope, stmt, .GreaterOrEqual, .AngleBracketRightEqual, ">=", true);1014 op_id = .GreaterOrEqual;
988 return maybeSuppressResult(rp, scope, result_used, TransResult{1015 op_token = try appendToken(rp.c, .AngleBracketRightEqual, ">=");
989 .node = node,
990 .child_scope = scope,
991 .node_scope = scope,
992 });
993 },1016 },
994 .EQ => {1017 .EQ => {
995 const node = try transCreateNodeInfixOp(rp, scope, stmt, .EqualEqual, .EqualEqual, "==", true);1018 op_id = .EqualEqual;
996 return maybeSuppressResult(rp, scope, result_used, TransResult{1019 op_token = try appendToken(rp.c, .EqualEqual, "==");
997 .node = node,
998 .child_scope = scope,
999 .node_scope = scope,
1000 });
1001 },1020 },
1002 .NE => {1021 .NE => {
1003 const node = try transCreateNodeInfixOp(rp, scope, stmt, .BangEqual, .BangEqual, "!=", true);1022 op_id = .BangEqual;
1004 return maybeSuppressResult(rp, scope, result_used, TransResult{1023 op_token = try appendToken(rp.c, .BangEqual, "!=");
1005 .node = node,
1006 .child_scope = scope,
1007 .node_scope = scope,
1008 });
1009 },1024 },
1010 .And => {1025 .And => {
1011 const node = try transCreateNodeInfixOp(rp, scope, stmt, .BitAnd, .Ampersand, "&", true);1026 op_id = .BitAnd;
1012 return maybeSuppressResult(rp, scope, result_used, TransResult{1027 op_token = try appendToken(rp.c, .Ampersand, "&");
1013 .node = node,
1014 .child_scope = scope,
1015 .node_scope = scope,
1016 });
1017 },1028 },
1018 .Xor => {1029 .Xor => {
1019 const node = try transCreateNodeInfixOp(rp, scope, stmt, .BitXor, .Caret, "^", true);1030 op_id = .BitXor;
1020 return maybeSuppressResult(rp, scope, result_used, TransResult{1031 op_token = try appendToken(rp.c, .Caret, "^");
1021 .node = node,
1022 .child_scope = scope,
1023 .node_scope = scope,
1024 });
1025 },1032 },
1026 .Or => {1033 .Or => {
1027 const node = try transCreateNodeInfixOp(rp, scope, stmt, .BitOr, .Pipe, "|", true);1034 op_id = .BitOr;
1028 return maybeSuppressResult(rp, scope, result_used, TransResult{1035 op_token = try appendToken(rp.c, .Pipe, "|");
1029 .node = node,
1030 .child_scope = scope,
1031 .node_scope = scope,
1032 });
1033 },
1034 .LAnd => {
1035 const node = try transCreateNodeBoolInfixOp(rp, scope, stmt, .BoolAnd, .Keyword_and, "and");
1036 return maybeSuppressResult(rp, scope, result_used, TransResult{
1037 .node = node,
1038 .child_scope = scope,
1039 .node_scope = scope,
1040 });
1041 },
1042 .LOr => {
1043 const node = try transCreateNodeBoolInfixOp(rp, scope, stmt, .BoolOr, .Keyword_or, "or");
1044 return maybeSuppressResult(rp, scope, result_used, TransResult{
1045 .node = node,
1046 .child_scope = scope,
1047 .node_scope = scope,
1048 });
1049 },
1050 .Comma => {
1051 const block_scope = try scope.findBlockScope(rp.c);
1052 const expr = block_scope.base.parent == scope;
1053 const lparen = if (expr) blk: {
1054 const l = try appendToken(rp.c, .LParen, "(");
1055 block_scope.block_node = try transCreateNodeBlock(rp.c, block_scope.label);
1056 break :blk l;
1057 } else undefined;
1058
1059 const lhs = try transExpr(rp, &block_scope.base, ZigClangBinaryOperator_getLHS(stmt), .unused, .r_value);
1060 try block_scope.block_node.statements.push(lhs);
1061
1062 const rhs = try transExpr(rp, &block_scope.base, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value);
1063 if (expr) {
1064 _ = try appendToken(rp.c, .Semicolon, ";");
1065 const break_node = try transCreateNodeBreak(rp.c, block_scope.label);
1066 break_node.rhs = rhs;
1067 try block_scope.block_node.statements.push(&break_node.base);
1068 block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}");
1069 const rparen = try appendToken(rp.c, .RParen, ")");
1070 const grouped_expr = try rp.c.a().create(ast.Node.GroupedExpression);
1071 grouped_expr.* = .{
1072 .lparen = lparen,
1073 .expr = &block_scope.block_node.base,
1074 .rparen = rparen,
1075 };
1076 return maybeSuppressResult(rp, scope, result_used, &grouped_expr.base);
1077 } else {
1078 return maybeSuppressResult(rp, scope, result_used, rhs);
1079 }
1080 },1036 },
1037 .Assign,
1081 .MulAssign,1038 .MulAssign,
1082 .DivAssign,1039 .DivAssign,
1083 .RemAssign,1040 .RemAssign,
...@@ -1091,6 +1048,9 @@ fn transBinaryOperator(...@@ -1091,6 +1048,9 @@ fn transBinaryOperator(
1091 => unreachable,1048 => unreachable,
1092 else => unreachable,1049 else => unreachable,
1093 }1050 }
1051
1052 const rhs_node = try transExpr(rp, scope, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value);
1053 return transCreateNodeInfixOp(rp, scope, lhs_node, op_id, op_token, rhs_node, result_used, true);
1094}1054}
10951055
1096fn transCompoundStmtInline(1056fn transCompoundStmtInline(
...@@ -1231,56 +1191,22 @@ fn transImplicitCastExpr(...@@ -1231,56 +1191,22 @@ fn transImplicitCastExpr(
1231 }1191 }
1232}1192}
12331193
1234fn toEnumZeroCmp(
1235 rp: RestorePoint,
1236 scope: *Scope,
1237 expr: *ast.Node,
1238 generate_enum_node: fn (RestorePoint, *const struct_ZigClangType, source_loc: ZigClangSourceLocation) TransError!*ast.Node,
1239 enum_ty: *const struct_ZigClangType,
1240 enum_source_loc: ZigClangSourceLocation,
1241) !*ast.Node {
1242 // expr != @bitCast(EnumType, @as(@TagType(EnumType), 0))
1243
1244 // @bitCast(Enum,
1245 const bitcast = try transCreateNodeBuiltinFnCall(rp.c, "@bitCast");
1246 const bitcast_enum_identifier = try generate_enum_node(rp, enum_ty, enum_source_loc);
1247 try bitcast.params.push(bitcast_enum_identifier);
1248 _ = try appendToken(rp.c, .Comma, ",");
1249
1250 // @as(
1251 const cast_node = try transCreateNodeBuiltinFnCall(rp.c, "@as");
1252
1253 // @TagType(Enum),
1254 const tag_type = try transCreateNodeBuiltinFnCall(rp.c, "@TagType");
1255 const tag_type_enum_identifier = try generate_enum_node(rp, enum_ty, enum_source_loc);
1256 try tag_type.params.push(tag_type_enum_identifier);
1257 tag_type.rparen_token = try appendToken(rp.c, .RParen, ")");
1258 try cast_node.params.push(&tag_type.base);
1259 _ = try appendToken(rp.c, .Comma, ",");
1260
1261 // 0)
1262 const zero = try transCreateNodeInt(rp.c, 0);
1263 try cast_node.params.push(zero);
1264 cast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
1265
1266 try bitcast.params.push(&cast_node.base);
1267 bitcast.rparen_token = try appendToken(rp.c, .RParen, ")");
1268
1269 // expr != @bitCast(EnumType, @as(@TagType(EnumType), 0))
1270 return transCreateNodeNotEqual(rp, scope, expr, &bitcast.base);
1271}
1272
1273fn transBoolExpr(1194fn transBoolExpr(
1274 rp: RestorePoint,1195 rp: RestorePoint,
1275 scope: *Scope,1196 scope: *Scope,
1276 expr: *const ZigClangExpr,1197 expr: *const ZigClangExpr,
1277 used: ResultUsed,1198 used: ResultUsed,
1278 lrvalue: LRValue,1199 lrvalue: LRValue,
1279) !*ast.Node {1200 grouped: bool,
1201) TransError!*ast.Node {
1202 const lparen = if (grouped)
1203 try appendToken(rp.c, .LParen, "(")
1204 else
1205 undefined;
1280 var res = try transExpr(rp, scope, expr, used, lrvalue);1206 var res = try transExpr(rp, scope, expr, used, lrvalue);
12811207
1282 switch (res.node.id) {1208 switch (res.id) {
1283 .InfixOp => switch (@ptrCast(*const ast.Node.InfixOp, &res.node).op) {1209 .InfixOp => switch (@fieldParentPtr(ast.Node.InfixOp, "base", res).op) {
1284 .BoolOr,1210 .BoolOr,
1285 .BoolAnd,1211 .BoolAnd,
1286 .EqualEqual,1212 .EqualEqual,
...@@ -1289,24 +1215,34 @@ fn transBoolExpr(...@@ -1289,24 +1215,34 @@ fn transBoolExpr(
1289 .GreaterThan,1215 .GreaterThan,
1290 .LessOrEqual,1216 .LessOrEqual,
1291 .GreaterOrEqual,1217 .GreaterOrEqual,
1292 => return res.node,1218 => return res,
12931219
1294 else => {},1220 else => {},
1295 },1221 },
12961222
1297 .PrefixOp => switch (@ptrCast(*const ast.Node.PrefixOp, &res.node).op) {1223 .PrefixOp => switch (@fieldParentPtr(ast.Node.PrefixOp, "base", res).op) {
1298 .BoolNot => return res.node,1224 .BoolNot => return res,
12991225
1300 else => {},1226 else => {},
1301 },1227 },
13021228
1303 .BoolLiteral => return res.node,1229 .BoolLiteral => return res,
13041230
1305 else => {},1231 else => {},
1306 }1232 }
1307
1308 const ty = ZigClangQualType_getTypePtr(getExprQualTypeBeforeImplicitCast(rp.c, expr));1233 const ty = ZigClangQualType_getTypePtr(getExprQualTypeBeforeImplicitCast(rp.c, expr));
1234 return finishBoolExpr(rp, scope, ZigClangExpr_getBeginLoc(expr), ty, res, used, grouped);
1235}
13091236
1237fn finishBoolExpr(
1238 rp: RestorePoint,
1239 scope: *Scope,
1240 loc: ZigClangSourceLocation,
1241 ty: *const ZigClangType,
1242 node: *ast.Node,
1243 used: ResultUsed,
1244 grouped: bool,
1245) TransError!*ast.Node {
1310 switch (ZigClangType_getTypeClass(ty)) {1246 switch (ZigClangType_getTypeClass(ty)) {
1311 .Builtin => {1247 .Builtin => {
1312 const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty);1248 const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty);
...@@ -1337,219 +1273,48 @@ fn transBoolExpr(...@@ -1337,219 +1273,48 @@ fn transBoolExpr(
1337 .Char32,1273 .Char32,
1338 .WChar_S,1274 .WChar_S,
1339 .Float16,1275 .Float16,
1340 => return transCreateNodeNotEqual(rp, scope, res.node, try transCreateNodeInt(rp.c, 0)),1276 => {
13411277 const op_token = try appendToken(rp.c, .BangEqual, "!=");
1342 .NullPtr => return transCreateNodeNotEqual(rp, scope, res.node, try transCreateNodeNullLiteral(rp.c)),1278 const rhs_node = try transCreateNodeInt(rp.c, 0);
13431279 return transCreateNodeInfixOp(rp, scope, node, .BangEqual, op_token, rhs_node, used, grouped);
1344 .Void,1280 },
1345 .Half,1281 .NullPtr => {
1346 .ObjCId,1282 const op_token = try appendToken(rp.c, .EqualEqual, "==");
1347 .ObjCClass,1283 const rhs_node = try transCreateNodeNullLiteral(rp.c);
1348 .ObjCSel,1284 return transCreateNodeInfixOp(rp, scope, node, .EqualEqual, op_token, rhs_node, used, grouped);
1349 .OMPArraySection,1285 },
1350 .Dependent,
1351 .Overload,
1352 .BoundMember,
1353 .PseudoObject,
1354 .UnknownAny,
1355 .BuiltinFn,
1356 .ARCUnbridgedCast,
1357 .OCLImage1dRO,
1358 .OCLImage1dArrayRO,
1359 .OCLImage1dBufferRO,
1360 .OCLImage2dRO,
1361 .OCLImage2dArrayRO,
1362 .OCLImage2dDepthRO,
1363 .OCLImage2dArrayDepthRO,
1364 .OCLImage2dMSAARO,
1365 .OCLImage2dArrayMSAARO,
1366 .OCLImage2dMSAADepthRO,
1367 .OCLImage2dArrayMSAADepthRO,
1368 .OCLImage3dRO,
1369 .OCLImage1dWO,
1370 .OCLImage1dArrayWO,
1371 .OCLImage1dBufferWO,
1372 .OCLImage2dWO,
1373 .OCLImage2dArrayWO,
1374 .OCLImage2dDepthWO,
1375 .OCLImage2dArrayDepthWO,
1376 .OCLImage2dMSAAWO,
1377 .OCLImage2dArrayMSAAWO,
1378 .OCLImage2dMSAADepthWO,
1379 .OCLImage2dArrayMSAADepthWO,
1380 .OCLImage3dWO,
1381 .OCLImage1dRW,
1382 .OCLImage1dArrayRW,
1383 .OCLImage1dBufferRW,
1384 .OCLImage2dRW,
1385 .OCLImage2dArrayRW,
1386 .OCLImage2dDepthRW,
1387 .OCLImage2dArrayDepthRW,
1388 .OCLImage2dMSAARW,
1389 .OCLImage2dArrayMSAARW,
1390 .OCLImage2dMSAADepthRW,
1391 .OCLImage2dArrayMSAADepthRW,
1392 .OCLImage3dRW,
1393 .OCLSampler,
1394 .OCLEvent,
1395 .OCLClkEvent,
1396 .OCLQueue,
1397 .OCLReserveID,
1398 .ShortAccum,
1399 .Accum,
1400 .LongAccum,
1401 .UShortAccum,
1402 .UAccum,
1403 .ULongAccum,
1404 .ShortFract,
1405 .Fract,
1406 .LongFract,
1407 .UShortFract,
1408 .UFract,
1409 .ULongFract,
1410 .SatShortAccum,
1411 .SatAccum,
1412 .SatLongAccum,
1413 .SatUShortAccum,
1414 .SatUAccum,
1415 .SatULongAccum,
1416 .SatShortFract,
1417 .SatFract,
1418 .SatLongFract,
1419 .SatUShortFract,
1420 .SatUFract,
1421 .SatULongFract,
1422 .OCLIntelSubgroupAVCMcePayload,
1423 .OCLIntelSubgroupAVCImePayload,
1424 .OCLIntelSubgroupAVCRefPayload,
1425 .OCLIntelSubgroupAVCSicPayload,
1426 .OCLIntelSubgroupAVCMceResult,
1427 .OCLIntelSubgroupAVCImeResult,
1428 .OCLIntelSubgroupAVCRefResult,
1429 .OCLIntelSubgroupAVCSicResult,
1430 .OCLIntelSubgroupAVCImeResultSingleRefStreamout,
1431 .OCLIntelSubgroupAVCImeResultDualRefStreamout,
1432 .OCLIntelSubgroupAVCImeSingleRefStreamin,
1433 .OCLIntelSubgroupAVCImeDualRefStreamin,
1434 => return res.node,
1435
1436 else => {},1286 else => {},
1437 }1287 }
1438 },1288 },
1439 .Pointer => return transCreateNodeNotEqual(rp, scope, res.node, try transCreateNodeNullLiteral(rp.c)),1289 .Pointer => {
14401290 const op_token = try appendToken(rp.c, .BangEqual, "!=");
1291 const rhs_node = try transCreateNodeNullLiteral(rp.c);
1292 return transCreateNodeInfixOp(rp, scope, node, .BangEqual, op_token, rhs_node, used, grouped);
1293 },
1441 .Typedef => {1294 .Typedef => {
1442 return transCreateNodeNotEqual(rp, scope, res.node, try transCreateNodeInt(rp.c, 0)); // TODO currently assuming it is like an int/char/bool builtin type. Coerce the type and recurse? Add a toTypedefZeroCmp function?1295 const typedef_ty = @ptrCast(*const ZigClangTypedefType, ty);
14431296 const typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
1444 // TODO This is the code that was in translate-c, but it seems like it is giving wrong results! It just prints the typedef name instead of the value1297 const underlying_type = ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl);
1445 // const typedef_ty = @ptrCast(*const ZigClangTypedefType, ty);1298 return finishBoolExpr(rp, scope, loc, ZigClangQualType_getTypePtr(underlying_type), node, used, grouped);
1446 // const typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
1447 // const typedef_name_decl = ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl);
1448
1449 // const typedef_name = if (rp.c.decl_table.get(@ptrToInt(typedef_name_decl))) |existing_entry|
1450 // existing_entry.value
1451 // else
1452 // try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, typedef_name_decl)));
1453
1454 // return transCreateNodeIdentifier(rp.c, typedef_name);
1455 },1299 },
1456
1457 .Enum => {1300 .Enum => {
1458 const gen_enum_decl_node = struct {1301 const enum_ty = @ptrCast(*const ZigClangEnumType, ty);
1459 // Have to use a callback because node must be generated inline in order to avoid weird AST printing behavior,1302 const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "@enumToInt");
1460 // and the code to generate the nodes is a little different for each case1303 try builtin_node.params.push(node);
1461 fn generate_node(inner_rp: RestorePoint, enum_ty: *const struct_ZigClangType, source_loc: ZigClangSourceLocation) TransError!*ast.Node {1304 builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
1462 const actual_enum_ty = @ptrCast(*const ZigClangEnumType, enum_ty);
1463 const enum_decl = ZigClangEnumType_getDecl(actual_enum_ty);
1464 const enum_type = (try transEnumDecl(inner_rp.c, enum_decl)) orelse {
1465 return revertAndWarn(inner_rp, error.UnsupportedType, source_loc, "unable to translate enum declaration", .{});
1466 };
1467 return enum_type;
1468 }
1469 };
14701305
1471 return toEnumZeroCmp(rp, scope, res.node, gen_enum_decl_node.generate_node, ty, ZigClangExpr_getBeginLoc(expr));1306 const op_token = try appendToken(rp.c, .BangEqual, "!=");
1307 const rhs_node = try transCreateNodeInt(rp.c, 0);
1308 return transCreateNodeInfixOp(rp, scope, &builtin_node.base, .BangEqual, op_token, rhs_node, used, grouped);
1472 },1309 },
1473
1474 .Elaborated => {1310 .Elaborated => {
1475 const elaborated_ty = @ptrCast(*const ZigClangElaboratedType, ty);1311 const elaborated_ty = @ptrCast(*const ZigClangElaboratedType, ty);
14761312 const named_type = ZigClangElaboratedType_getNamedType(elaborated_ty);
1477 switch (ZigClangElaboratedType_getKeyword(elaborated_ty)) {1313 return finishBoolExpr(rp, scope, loc, ZigClangQualType_getTypePtr(named_type), node, used, grouped);
1478 .Enum => {
1479 // Have to use a callback because node must be generated inline in order to avoid weird AST printing behavior,
1480 // and the code to generate the nodes is a little different for each case
1481 const gen_enum_type_node = struct {
1482 fn generate_node(inner_rp: RestorePoint, enum_ty: *const struct_ZigClangType, source_loc: ZigClangSourceLocation) TransError!*ast.Node {
1483 const inner_elaborated_ty = @ptrCast(*const ZigClangElaboratedType, enum_ty);
1484 const enum_type = try transQualType(inner_rp, ZigClangElaboratedType_getNamedType(inner_elaborated_ty), source_loc);
1485 return enum_type;
1486 }
1487 };
1488
1489 return toEnumZeroCmp(rp, scope, res.node, gen_enum_type_node.generate_node, ty, ZigClangExpr_getBeginLoc(expr));
1490 },
1491
1492 .Struct,
1493 .Union,
1494 .Interface,
1495 .Class,
1496 .Typename,
1497 .None,
1498 => return res.node,
1499
1500 else => {},
1501 }
1502 },1314 },
15031315 else => {},
1504 .FunctionProto,
1505 .Record,
1506 .ConstantArray,
1507 .Paren,
1508 .Decayed,
1509 .Attributed,
1510 .IncompleteArray,
1511 .BlockPointer,
1512 .LValueReference,
1513 .RValueReference,
1514 .MemberPointer,
1515 .VariableArray,
1516 .DependentSizedArray,
1517 .DependentSizedExtVector,
1518 .Vector,
1519 .ExtVector,
1520 .FunctionNoProto,
1521 .UnresolvedUsing,
1522 .Adjusted,
1523 .TypeOfExpr,
1524 .TypeOf,
1525 .Decltype,
1526 .UnaryTransform,
1527 .TemplateTypeParm,
1528 .SubstTemplateTypeParm,
1529 .SubstTemplateTypeParmPack,
1530 .TemplateSpecialization,
1531 .Auto,
1532 .InjectedClassName,
1533 .DependentName,
1534 .DependentTemplateSpecialization,
1535 .PackExpansion,
1536 .ObjCObject,
1537 .ObjCInterface,
1538 .Complex,
1539 .ObjCObjectPointer,
1540 .Atomic,
1541 .Pipe,
1542 .ObjCTypeParam,
1543 .DeducedTemplateSpecialization,
1544 .DependentAddressSpace,
1545 .DependentVector,
1546 .MacroQualified,
1547 => return res.node,
1548
1549 else => unreachable,
1550 }1316 }
15511317 return revertAndWarn(rp, error.UnsupportedType, loc, "unsupported bool expression type", .{});
1552 unreachable;
1553}1318}
15541319
1555fn transIntegerLiteral(1320fn transIntegerLiteral(
...@@ -2036,7 +1801,6 @@ fn transSwitch(...@@ -2036,7 +1801,6 @@ fn transSwitch(
2036 const switch_block = try transCreateNodeBlock(rp.c, null);1801 const switch_block = try transCreateNodeBlock(rp.c, null);
2037 try switch_block.statements.push(&switch_node.base);1802 try switch_block.statements.push(&switch_node.base);
2038 switch_scope.pending_block = switch_block;1803 switch_scope.pending_block = switch_block;
2039
20401804
2041 const last = try transStmt(rp, &block_scope.base, ZigClangSwitchStmt_getBody(stmt), .unused, .r_value);1805 const last = try transStmt(rp, &block_scope.base, ZigClangSwitchStmt_getBody(stmt), .unused, .r_value);
2042 _ = try appendToken(rp.c, .Semicolon, ";");1806 _ = try appendToken(rp.c, .Semicolon, ";");
...@@ -2085,7 +1849,6 @@ fn transCase(...@@ -2085,7 +1849,6 @@ fn transCase(
2085 } else1849 } else
2086 try transExpr(rp, scope, ZigClangCaseStmt_getLHS(stmt), .used, .r_value);1850 try transExpr(rp, scope, ZigClangCaseStmt_getLHS(stmt), .used, .r_value);
20871851
2088
2089 const switch_prong = try transCreateNodeSwitchCase(rp.c, expr);1852 const switch_prong = try transCreateNodeSwitchCase(rp.c, expr);
2090 switch_prong.expr = &(try transCreateNodeBreak(rp.c, label)).base;1853 switch_prong.expr = &(try transCreateNodeBreak(rp.c, label)).base;
2091 _ = try appendToken(rp.c, .Comma, ",");1854 _ = try appendToken(rp.c, .Comma, ",");
...@@ -2271,7 +2034,7 @@ fn transConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const ZigCla...@@ -2271,7 +2034,7 @@ fn transConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const ZigCla
2271 const grouped_expr = try rp.c.a().create(ast.Node.GroupedExpression);2034 const grouped_expr = try rp.c.a().create(ast.Node.GroupedExpression);
2272 grouped_expr.* = .{2035 grouped_expr.* = .{
2273 .lparen = lparen,2036 .lparen = lparen,
2274 .expr = &if_node.base,2037 .expr = &if_node.base,
2275 .rparen = rparen,2038 .rparen = rparen,
2276 };2039 };
2277 return maybeSuppressResult(rp, scope, used, &grouped_expr.base);2040 return maybeSuppressResult(rp, scope, used, &grouped_expr.base);
...@@ -2670,87 +2433,64 @@ fn transCreateNodePrefixOp(...@@ -2670,87 +2433,64 @@ fn transCreateNodePrefixOp(
2670 return node;2433 return node;
2671}2434}
26722435
2673fn transCreateNodeInfixOpImpl(2436fn transCreateNodeInfixOp(
2674 rp: RestorePoint,2437 rp: RestorePoint,
2675 scope: *Scope,2438 scope: *Scope,
2676 lhs_node: *ast.Node,2439 lhs_node: *ast.Node,
2677 rhs_node: *ast.Node,
2678 op: ast.Node.InfixOp.Op,2440 op: ast.Node.InfixOp.Op,
2679 op_tok_id: std.zig.Token.Id,2441 op_token: ast.TokenIndex,
2680 bytes: []const u8,2442 rhs_node: *ast.Node,
2443 used: ResultUsed,
2681 grouped: bool,2444 grouped: bool,
2682) !*ast.Node {2445) !*ast.Node {
2683 const lparen = if (grouped) try appendToken(rp.c, .LParen, "(") else undefined;2446 var lparen = if (grouped)
2684 const op_token = try appendToken(rp.c, op_tok_id, bytes);2447 try appendToken(rp.c, .LParen, "(")
2448 else
2449 null;
2685 const node = try rp.c.a().create(ast.Node.InfixOp);2450 const node = try rp.c.a().create(ast.Node.InfixOp);
2686 node.* = ast.Node.InfixOp{2451 node.* = .{
2687 .op_token = op_token,2452 .op_token = op_token,
2688 .lhs = lhs_node,2453 .lhs = lhs_node,
2689 .op = op,2454 .op = op,
2690 .rhs = rhs_node,2455 .rhs = rhs_node,
2691 };2456 };
2692 if (!grouped) return &node.base;2457 if (!grouped) return maybeSuppressResult(rp, scope, used, &node.base);
2693 const rparen = try appendToken(rp.c, .RParen, ")");2458 const rparen = try appendToken(rp.c, .RParen, ")");
2694 const grouped_expr = try rp.c.a().create(ast.Node.GroupedExpression);2459 const grouped_expr = try rp.c.a().create(ast.Node.GroupedExpression);
2695 grouped_expr.* = .{2460 grouped_expr.* = .{
2696 .lparen = lparen,2461 .lparen = lparen.?,
2697 .expr = &node.base,2462 .expr = &node.base,
2698 .rparen = rparen,2463 .rparen = rparen,
2699 };2464 };
2700 return &grouped_expr.base;2465 return maybeSuppressResult(rp, scope, used, &grouped_expr.base);
2701}2466}
27022467
2703fn transCreateNodeInfixOp(2468fn transCreateNodeBoolInfixOp(
2704 rp: RestorePoint,2469 rp: RestorePoint,
2705 scope: *Scope,2470 scope: *Scope,
2706 stmt: *const ZigClangBinaryOperator,2471 stmt: *const ZigClangBinaryOperator,
2707 op: ast.Node.InfixOp.Op,2472 op: ast.Node.InfixOp.Op,
2708 op_tok_id: std.zig.Token.Id,2473 used: ResultUsed,
2709 bytes: []const u8,
2710 grouped: bool,2474 grouped: bool,
2711) !*ast.Node {2475) !*ast.Node {
2712 return transCreateNodeInfixOpImpl(2476 std.debug.assert(op == .BoolAnd or op == .BoolOr);
2713 rp,
2714 scope,
2715 (try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .r_value)).node,
2716 (try transExpr(rp, scope, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value)).node,
2717 op,
2718 op_tok_id,
2719 bytes,
2720 grouped,
2721 );
2722}
2723
2724fn transCreateNodeNotEqual(
2725 rp: RestorePoint,
2726 scope: *Scope,
2727 lhs_node: *ast.Node,
2728 rhs_node: *ast.Node,
2729) !*ast.Node {
2730 return transCreateNodeInfixOpImpl(rp, scope, lhs_node, rhs_node, .BangEqual, .BangEqual, "!=", true);
2731}
27322477
2733fn transCreateNodeBoolInfixOp(2478 const lhs_hode = try transBoolExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value, true);
2734 rp: RestorePoint,2479 const op_token = if (op == .BoolAnd)
2735 scope: *Scope,2480 try appendToken(rp.c, .Keyword_and, "and")
2736 stmt: *const ZigClangBinaryOperator,2481 else
2737 comptime op: ast.Node.InfixOp.Op,2482 try appendToken(rp.c, .Keyword_or, "or");
2738 comptime op_tok_id: std.zig.Token.Id,2483 const rhs = try transBoolExpr(rp, scope, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value, true);
2739 comptime bytes: []const u8,
2740) !*ast.Node {
2741 if (!(op == .BoolAnd or op == .BoolOr)) {
2742 @compileError("op must be either .BoolAnd or .BoolOr");
2743 }
27442484
2745 return transCreateNodeInfixOpImpl(2485 return transCreateNodeInfixOp(
2746 rp,2486 rp,
2747 scope,2487 scope,
2748 try transBoolExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .r_value),2488 lhs_hode,
2749 try transBoolExpr(rp, scope, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value),
2750 op,2489 op,
2751 op_tok_id,2490 op_token,
2752 bytes,2491 rhs,
2753 true,2492 used,
2493 grouped,
2754 );2494 );
2755}2495}
27562496
...@@ -3149,16 +2889,14 @@ fn transCreateNodeShiftOp(...@@ -3149,16 +2889,14 @@ fn transCreateNodeShiftOp(
3149 comptime op_tok_id: std.zig.Token.Id,2889 comptime op_tok_id: std.zig.Token.Id,
3150 comptime bytes: []const u8,2890 comptime bytes: []const u8,
3151) !*ast.Node {2891) !*ast.Node {
3152 if (!(op == .BitShiftLeft or op == .BitShiftRight)) {2892 std.debug.assert(op == .BitShiftLeft or op == .BitShiftRight);
3153 @compileError("op must be either .BitShiftLeft or .BitShiftRight");
3154 }
31552893
3156 const lhs_expr = ZigClangBinaryOperator_getLHS(stmt);2894 const lhs_expr = ZigClangBinaryOperator_getLHS(stmt);
3157 const rhs_expr = ZigClangBinaryOperator_getRHS(stmt);2895 const rhs_expr = ZigClangBinaryOperator_getRHS(stmt);
3158 const rhs_location = ZigClangExpr_getBeginLoc(rhs_expr);2896 const rhs_location = ZigClangExpr_getBeginLoc(rhs_expr);
3159 // lhs >> u5(rh)2897 // lhs >> u5(rh)
31602898
3161 const lhs = try transExpr(rp, scope, lhs_expr, .used, .r_value);2899 const lhs = try transExpr(rp, scope, lhs_expr, .used, .l_value);
3162 const op_token = try appendToken(rp.c, op_tok_id, bytes);2900 const op_token = try appendToken(rp.c, op_tok_id, bytes);
31632901
3164 const as_node = try transCreateNodeBuiltinFnCall(rp.c, "@as");2902 const as_node = try transCreateNodeBuiltinFnCall(rp.c, "@as");
...@@ -3166,13 +2904,13 @@ fn transCreateNodeShiftOp(...@@ -3166,13 +2904,13 @@ fn transCreateNodeShiftOp(
3166 try as_node.params.push(rhs_type);2904 try as_node.params.push(rhs_type);
3167 _ = try appendToken(rp.c, .Comma, ",");2905 _ = try appendToken(rp.c, .Comma, ",");
3168 const rhs = try transExpr(rp, scope, rhs_expr, .used, .r_value);2906 const rhs = try transExpr(rp, scope, rhs_expr, .used, .r_value);
3169 try as_node.params.push(rhs.node);2907 try as_node.params.push(rhs);
3170 as_node.rparen_token = try appendToken(rp.c, .RParen, ")");2908 as_node.rparen_token = try appendToken(rp.c, .RParen, ")");
31712909
3172 const node = try rp.c.a().create(ast.Node.InfixOp);2910 const node = try rp.c.a().create(ast.Node.InfixOp);
3173 node.* = ast.Node.InfixOp{2911 node.* = ast.Node.InfixOp{
3174 .op_token = op_token,2912 .op_token = op_token,
3175 .lhs = lhs.node,2913 .lhs = lhs,
3176 .op = op,2914 .op = op,
3177 .rhs = &as_node.base,2915 .rhs = &as_node.base,
3178 };2916 };
...@@ -3648,26 +3386,26 @@ fn isZigPrimitiveType(name: []const u8) bool {...@@ -3648,26 +3386,26 @@ fn isZigPrimitiveType(name: []const u8) bool {
3648 }3386 }
3649 // void is invalid in c so it doesn't need to be checked.3387 // void is invalid in c so it doesn't need to be checked.
3650 return std.mem.eql(u8, name, "comptime_float") or3388 return std.mem.eql(u8, name, "comptime_float") or
3651 std.mem.eql(u8, name, "comptime_int") or3389 std.mem.eql(u8, name, "comptime_int") or
3652 std.mem.eql(u8, name, "bool") or3390 std.mem.eql(u8, name, "bool") or
3653 std.mem.eql(u8, name, "isize") or3391 std.mem.eql(u8, name, "isize") or
3654 std.mem.eql(u8, name, "usize") or3392 std.mem.eql(u8, name, "usize") or
3655 std.mem.eql(u8, name, "f16") or3393 std.mem.eql(u8, name, "f16") or
3656 std.mem.eql(u8, name, "f32") or3394 std.mem.eql(u8, name, "f32") or
3657 std.mem.eql(u8, name, "f64") or3395 std.mem.eql(u8, name, "f64") or
3658 std.mem.eql(u8, name, "f128") or3396 std.mem.eql(u8, name, "f128") or
3659 std.mem.eql(u8, name, "c_longdouble") or3397 std.mem.eql(u8, name, "c_longdouble") or
3660 std.mem.eql(u8, name, "noreturn") or3398 std.mem.eql(u8, name, "noreturn") or
3661 std.mem.eql(u8, name, "type") or3399 std.mem.eql(u8, name, "type") or
3662 std.mem.eql(u8, name, "anyerror") or3400 std.mem.eql(u8, name, "anyerror") or
3663 std.mem.eql(u8, name, "c_short") or3401 std.mem.eql(u8, name, "c_short") or
3664 std.mem.eql(u8, name, "c_ushort") or3402 std.mem.eql(u8, name, "c_ushort") or
3665 std.mem.eql(u8, name, "c_int") or3403 std.mem.eql(u8, name, "c_int") or
3666 std.mem.eql(u8, name, "c_uint") or3404 std.mem.eql(u8, name, "c_uint") or
3667 std.mem.eql(u8, name, "c_long") or3405 std.mem.eql(u8, name, "c_long") or
3668 std.mem.eql(u8, name, "c_ulong") or3406 std.mem.eql(u8, name, "c_ulong") or
3669 std.mem.eql(u8, name, "c_longlong") or3407 std.mem.eql(u8, name, "c_longlong") or
3670 std.mem.eql(u8, name, "c_ulonglong");3408 std.mem.eql(u8, name, "c_ulonglong");
3671}3409}
36723410
3673fn isValidZigIdentifier(name: []const u8) bool {3411fn isValidZigIdentifier(name: []const u8) bool {
test/translate_c.zig+98-98
...@@ -531,33 +531,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -531,33 +531,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
531 \\}531 \\}
532 });532 });
533533
534 cases.add_2("qualified struct and enum",
535 \\struct Foo {
536 \\ int x;
537 \\ int y;
538 \\};
539 \\enum Bar {
540 \\ BarA,
541 \\ BarB,
542 \\};
543 \\void func(struct Foo *a, enum Bar **b);
544 , &[_][]const u8{
545 \\pub const struct_Foo = extern struct {
546 \\ x: c_int,
547 \\ y: c_int,
548 \\};
549 \\pub const BarA = enum_Bar.A;
550 \\pub const BarB = enum_Bar.B;
551 \\pub const enum_Bar = extern enum {
552 \\ A,
553 \\ B,
554 \\};
555 \\pub extern fn func(a: [*c]struct_Foo, b: [*c][*c]enum_Bar) void;
556 ,
557 \\pub const Foo = struct_Foo;
558 \\pub const Bar = enum_Bar;
559 });
560
561 cases.add_both("constant size array",534 cases.add_both("constant size array",
562 \\void func(int array[20]);535 \\void func(int array[20]);
563 , &[_][]const u8{536 , &[_][]const u8{
...@@ -1388,17 +1361,109 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1388,17 +1361,109 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1388 \\ var h: c_int = ((a != 0) or (b != 0));1361 \\ var h: c_int = ((a != 0) or (b != 0));
1389 \\ var i: c_int = ((b != 0) or (c != null));1362 \\ var i: c_int = ((b != 0) or (c != null));
1390 \\ var j: c_int = ((a != 0) or (c != null));1363 \\ var j: c_int = ((a != 0) or (c != null));
1391 \\ var k: c_int = ((a != 0) or (@as(c_int, d) != @bitCast(enum_Foo, @as(@TagType(enum_Foo), 0))));1364 \\ var k: c_int = ((a != 0) or (@enumToInt(@as(c_uint, d)) != 0));
1392 \\ var l: c_int = ((@as(c_int, d) != @bitCast(enum_Foo, @as(@TagType(enum_Foo), 0))) and (b != 0));1365 \\ var l: c_int = ((@enumToInt(@as(c_uint, d)) != 0) and (b != 0));
1393 \\ var m: c_int = ((c != null) or (@as(c_int, d) != @bitCast(enum_Foo, @as(@TagType(enum_Foo), 0))));1366 \\ var m: c_int = ((c != null) or (@enumToInt(@as(c_uint, d)) != 0));
1394 \\ var td: SomeTypedef = 44;1367 \\ var td: SomeTypedef = 44;
1395 \\ var o: c_int = ((td != 0) or (b != 0));1368 \\ var o: c_int = ((td != 0) or (b != 0));
1396 \\ var p: c_int = ((c != null) and (td != 0));1369 \\ var p: c_int = ((c != null) and (td != 0));
1397 \\ return ((((((((((e + f) + g) + h) + i) + j) + k) + l) + m) + o) + p);1370 \\ return ((((((((((e + f) + g) + h) + i) + j) + k) + l) + m) + o) + p);
1398 \\}1371 \\}
1372 ,
1399 \\pub const Foo = enum_Foo;1373 \\pub const Foo = enum_Foo;
1400 });1374 });
14011375
1376 cases.add_2("qualified struct and enum",
1377 \\struct Foo {
1378 \\ int x;
1379 \\ int y;
1380 \\};
1381 \\enum Bar {
1382 \\ BarA,
1383 \\ BarB,
1384 \\};
1385 \\void func(struct Foo *a, enum Bar **b);
1386 , &[_][]const u8{
1387 \\pub const struct_Foo = extern struct {
1388 \\ x: c_int,
1389 \\ y: c_int,
1390 \\};
1391 \\pub const BarA = enum_Bar.A;
1392 \\pub const BarB = enum_Bar.B;
1393 \\pub const enum_Bar = extern enum {
1394 \\ A,
1395 \\ B,
1396 \\};
1397 \\pub extern fn func(a: [*c]struct_Foo, b: [*c][*c]enum_Bar) void;
1398 ,
1399 \\pub const Foo = struct_Foo;
1400 \\pub const Bar = enum_Bar;
1401 });
1402
1403 cases.add_2("bitwise binary operators, simpler parens", // TODO can combine with "bitwise binary operators" when parens are correctly preserved/not added in translate-c-2
1404 \\int max(int a, int b) {
1405 \\ int c = (a & b);
1406 \\ int d = (a | b);
1407 \\ return (c ^ d);
1408 \\}
1409 , &[_][]const u8{
1410 \\pub export fn max(a: c_int, b: c_int) c_int {
1411 \\ var c: c_int = (a & b);
1412 \\ var d: c_int = (a | b);
1413 \\ return (c ^ d);
1414 \\}
1415 });
1416
1417 cases.add_2("comparison operators (no if)", // TODO Come up with less contrived tests? Make sure to cover all these comparisons. Can use `if` after it is added to translate-c-2
1418 \\int test_comparisons(int a, int b) {
1419 \\ int c = (a < b);
1420 \\ int d = (a > b);
1421 \\ int e = (a <= b);
1422 \\ int f = (a >= b);
1423 \\ int g = (c < d);
1424 \\ int h = (e < f);
1425 \\ int i = (g < h);
1426 \\ return i;
1427 \\}
1428 , &[_][]const u8{
1429 \\pub export fn test_comparisons(a: c_int, b: c_int) c_int {
1430 \\ var c: c_int = (a < b);
1431 \\ var d: c_int = (a > b);
1432 \\ var e: c_int = (a <= b);
1433 \\ var f: c_int = (a >= b);
1434 \\ var g: c_int = (c < d);
1435 \\ var h: c_int = (e < f);
1436 \\ var i: c_int = (g < h);
1437 \\ return i;
1438 \\}
1439 });
1440
1441 cases.add_2("==, !=, no if", // TODO remove this test after `if` conversion supported, and switch "==, !=" to addC_both
1442 \\int max(int a, int b) {
1443 \\ int c = (a == b);
1444 \\ int d = (a != b);
1445 \\ return (c != d);
1446 \\}
1447 , &[_][]const u8{
1448 \\pub export fn max(a: c_int, b: c_int) c_int {
1449 \\ var c: c_int = (a == b);
1450 \\ var d: c_int = (a != b);
1451 \\ return (c != d);
1452 \\}
1453 });
1454
1455 cases.add_2("bitshift, no parens", // TODO can fold this into "bitshift" once parens are preserved correctly in translate-c-2
1456 \\int foo(void) {
1457 \\ int a = (1 << 2);
1458 \\ return a >> 1;
1459 \\}
1460 , &[_][]const u8{
1461 \\pub export fn foo() c_int {
1462 \\ var a: c_int = 1 << @as(@import("std").math.Log2Int(c_int), 2);
1463 \\ return a >> @as(@import("std").math.Log2Int(c_int), 1);
1464 \\}
1465 });
1466
1402 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////1467 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
14031468
1404 cases.addAllowWarnings("simple data types",1469 cases.addAllowWarnings("simple data types",
...@@ -1525,21 +1590,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1525,21 +1590,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1525 \\ return a;1590 \\ return a;
1526 \\}1591 \\}
1527 });1592 });
1528
1529 cases.add_2("==, !=, no if", // TODO remove this test after `if` conversion supported, and switch "==, !=" to addC_both
1530 \\int max(int a, int b) {
1531 \\ int c = (a == b);
1532 \\ int d = (a != b);
1533 \\ return (c != d);
1534 \\}
1535 , &[_][]const u8{
1536 \\pub export fn max(a: c_int, b: c_int) c_int {
1537 \\ var c: c_int = (a == b);
1538 \\ var d: c_int = (a != b);
1539 \\ return (c != d);
1540 \\}
1541 });
1542
1543 cases.addC("bitwise binary operators",1593 cases.addC("bitwise binary operators",
1544 \\int max(int a, int b) {1594 \\int max(int a, int b) {
1545 \\ return (a & b) ^ (a | b);1595 \\ return (a & b) ^ (a | b);
...@@ -1550,20 +1600,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1550,20 +1600,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1550 \\}1600 \\}
1551 });1601 });
15521602
1553 cases.add_2("bitwise binary operators, simpler parens", // TODO can combine with "bitwise binary operators" when parens are correctly preserved/not added in translate-c-2
1554 \\int max(int a, int b) {
1555 \\ int c = (a & b);
1556 \\ int d = (a | b);
1557 \\ return (c ^ d);
1558 \\}
1559 , &[_][]const u8{
1560 \\pub export fn max(a: c_int, b: c_int) c_int {
1561 \\ var c: c_int = (a & b);
1562 \\ var d: c_int = (a | b);
1563 \\ return (c ^ d);
1564 \\}
1565 });
1566
1567 cases.addC("logical and, logical or",1603 cases.addC("logical and, logical or",
1568 \\int max(int a, int b) {1604 \\int max(int a, int b) {
1569 \\ if (a < b || a == b)1605 \\ if (a < b || a == b)
...@@ -1580,30 +1616,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1580,30 +1616,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1580 \\}1616 \\}
1581 });1617 });
15821618
1583 cases.add_2("comparison operators (no if)", // TODO Come up with less contrived tests? Make sure to cover all these comparisons. Can use `if` after it is added to translate-c-2
1584 \\int test_comparisons(int a, int b) {
1585 \\ int c = (a < b);
1586 \\ int d = (a > b);
1587 \\ int e = (a <= b);
1588 \\ int f = (a >= b);
1589 \\ int g = (c < d);
1590 \\ int h = (e < f);
1591 \\ int i = (g < h);
1592 \\ return i;
1593 \\}
1594 , &[_][]const u8{
1595 \\pub export fn test_comparisons(a: c_int, b: c_int) c_int {
1596 \\ var c: c_int = (a < b);
1597 \\ var d: c_int = (a > b);
1598 \\ var e: c_int = (a <= b);
1599 \\ var f: c_int = (a >= b);
1600 \\ var g: c_int = (c < d);
1601 \\ var h: c_int = (e < f);
1602 \\ var i: c_int = (g < h);
1603 \\ return i;
1604 \\}
1605 });
1606
1607 cases.addC("logical and, logical or, on non-bool values", // Note this gets cut off by extra C symbols being injected in middle: `pub const Foo = enum_Foo;`1619 cases.addC("logical and, logical or, on non-bool values", // Note this gets cut off by extra C symbols being injected in middle: `pub const Foo = enum_Foo;`
1608 \\enum Foo {1620 \\enum Foo {
1609 \\ FooA,1621 \\ FooA,
...@@ -1640,9 +1652,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1640,9 +1652,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1640 \\ var h: c_int = (a != 0) or (b != 0);1652 \\ var h: c_int = (a != 0) or (b != 0);
1641 \\ var i: c_int = (b != 0) or (c != null);1653 \\ var i: c_int = (b != 0) or (c != null);
1642 \\ var j: c_int = (a != 0) or (c != null);1654 \\ var j: c_int = (a != 0) or (c != null);
1643 \\ var k: c_int = (a != 0) or (@as(c_int, d) != @bitCast(enum_Foo, @as(@TagType(enum_Foo), 0)));1655 \\ var k: c_int = (a != 0) or (@as(c_uint, d) != @bitCast(enum_Foo, @as(@TagType(enum_Foo), 0)));
1644 \\ var l: c_int = (@as(c_int, d) != @bitCast(enum_Foo, @as(@TagType(enum_Foo), 0))) and (b != 0);1656 \\ var l: c_int = (@as(c_uint, d) != @bitCast(enum_Foo, @as(@TagType(enum_Foo), 0))) and (b != 0);
1645 \\ var m: c_int = (c != null) or (@as(c_int, d) != @bitCast(enum_Foo, @as(@TagType(enum_Foo), 0)));1657 \\ var m: c_int = (c != null) or (@as(c_uint, d) != @bitCast(enum_Foo, @as(@TagType(enum_Foo), 0)));
1646 \\ return (((((((e + f) + g) + h) + i) + j) + k) + l) + m;1658 \\ return (((((((e + f) + g) + h) + i) + j) + k) + l) + m;
1647 \\}1659 \\}
1648 });1660 });
...@@ -1760,18 +1772,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1760,18 +1772,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1760 \\}1772 \\}
1761 });1773 });
17621774
1763 cases.add_2("bitshift, no parens", // TODO can fold this into "bitshift" once parens are preserved correctly in translate-c-2
1764 \\int foo(void) {
1765 \\ int a = (1 << 2);
1766 \\ return a >> 1;
1767 \\}
1768 , &[_][]const u8{
1769 \\pub export fn foo() c_int {
1770 \\ var a: c_int = 1 << @as(@import("std").math.Log2Int(c_int), 2);
1771 \\ return a >> @as(@import("std").math.Log2Int(c_int), 1);
1772 \\}
1773 });
1774
1775 cases.addC("compound assignment operators",1775 cases.addC("compound assignment operators",
1776 \\void foo(void) {1776 \\void foo(void) {
1777 \\ int a = 0;1777 \\ int a = 0;