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 {
741741 InclusionDirectiveKind,
742742};
743743
744pub const ZigClangExpr_ConstExprUsage = extern enum {
745 EvaluateForCodeGen,
746 EvaluateForMangling,
747};
748
744749pub extern fn ZigClangSourceManager_getSpellingLoc(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) struct_ZigClangSourceLocation;
745750pub extern fn ZigClangSourceManager_getFilename(self: *const struct_ZigClangSourceManager, SpellingLoc: struct_ZigClangSourceLocation) ?[*:0]const u8;
746751pub 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 {
184184 .Ref => null,
185185 .FnDef => @fieldParentPtr(FnDef, "base", scope).getAlias(name),
186186 .Block => @fieldParentPtr(Block, "base", scope).getAlias(name),
187 .Switch,
188 .Loop,
189 .Condition => scope.parent.?.getAlias(name),
187 .Switch, .Loop, .Condition => scope.parent.?.getAlias(name),
190188 };
191189 }
192190
......@@ -196,9 +194,7 @@ const Scope = struct {
196194 .Root => @fieldParentPtr(Root, "base", scope).contains(name),
197195 .FnDef => @fieldParentPtr(FnDef, "base", scope).contains(name),
198196 .Block => @fieldParentPtr(Block, "base", scope).contains(name),
199 .Switch,
200 .Loop,
201 .Condition => scope.parent.?.contains(name),
197 .Switch, .Loop, .Condition => scope.parent.?.contains(name),
202198 };
203199 }
204200
......@@ -594,7 +590,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
594590 const node = try transCreateNodeVarDecl(c, true, true, name);
595591
596592 node.eq_token = try appendToken(c, .Equal, "=");
597
593
598594 var semicolon: ast.TokenIndex = undefined;
599595 node.init_node = blk: {
600596 const rp = makeRestorePoint(c);
......@@ -634,12 +630,12 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
634630 const field_name = try appendIdentifier(c, try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, field_decl))));
635631 _ = try appendToken(c, .Colon, ":");
636632 const field_type = transQualType(rp, ZigClangFieldDecl_getType(field_decl), field_loc) catch |err| switch (err) {
637 error.UnsupportedType => {
638 try failDecl(c, record_loc, name, "unable to translate {} member type", .{container_kind_name});
639 return null;
640 },
641 else => |e| return e,
642 };
633 error.UnsupportedType => {
634 try failDecl(c, record_loc, name, "unable to translate {} member type", .{container_kind_name});
635 return null;
636 },
637 else => |e| return e,
638 };
643639
644640 const field_node = try c.a().create(ast.Node.ContainerField);
645641 field_node.* = .{
......@@ -879,205 +875,166 @@ fn transBinaryOperator(
879875) TransError!*ast.Node {
880876 const op = ZigClangBinaryOperator_getOpcode(stmt);
881877 const qt = ZigClangBinaryOperator_getType(stmt);
878 var op_token: ast.TokenIndex = undefined;
879 var op_id: ast.Node.InfixOp.Op = undefined;
882880 switch (op) {
883 .PtrMemD, .PtrMemI, .Cmp => return revertAndWarn(
884 rp,
885 error.UnsupportedTranslation,
886 ZigClangBinaryOperator_getBeginLoc(stmt),
887 "TODO: handle more C binary operators: {}",
888 .{op},
889 ),
890 .Assign => return try transCreateNodeAssign(rp, scope, result_used, ZigClangBinaryOperator_getLHS(stmt), ZigClangBinaryOperator_getRHS(stmt)),
891 .Add => {
892 const node = if (cIsUnsignedInteger(qt))
893 try transCreateNodeInfixOp(rp, scope, stmt, .AddWrap, .PlusPercent, "+%", true)
894 else
895 try transCreateNodeInfixOp(rp, scope, stmt, .Add, .Plus, "+", true);
896 return maybeSuppressResult(rp, scope, result_used, node);
897 },
898 .Sub => {
899 const node = if (cIsUnsignedInteger(qt))
900 try transCreateNodeInfixOp(rp, scope, stmt, .SubWrap, .MinusPercent, "-%", true)
901 else
902 try transCreateNodeInfixOp(rp, scope, stmt, .Sub, .Minus, "-", true);
903 return maybeSuppressResult(rp, scope, result_used, node);
904 },
905 .Mul => {
906 const node = if (cIsUnsignedInteger(qt))
907 try transCreateNodeInfixOp(rp, scope, stmt, .MultWrap, .AsteriskPercent, "*%", true)
908 else
909 try transCreateNodeInfixOp(rp, scope, stmt, .Mult, .Asterisk, "*", true);
910 return maybeSuppressResult(rp, scope, result_used, node);
881 .Assign => return transCreateNodeAssign(rp, scope, result_used, ZigClangBinaryOperator_getLHS(stmt), ZigClangBinaryOperator_getRHS(stmt)),
882 .Comma => {
883 const block_scope = try scope.findBlockScope(rp.c);
884 const expr = block_scope.base.parent == scope;
885 const lparen = if (expr) blk: {
886 const l = try appendToken(rp.c, .LParen, "(");
887 block_scope.block_node = try transCreateNodeBlock(rp.c, block_scope.label);
888 break :blk l;
889 } else undefined;
890
891 const lhs = try transExpr(rp, &block_scope.base, ZigClangBinaryOperator_getLHS(stmt), .unused, .r_value);
892 try block_scope.block_node.statements.push(lhs);
893
894 const rhs = try transExpr(rp, &block_scope.base, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value);
895 if (expr) {
896 _ = try appendToken(rp.c, .Semicolon, ";");
897 const break_node = try transCreateNodeBreak(rp.c, block_scope.label);
898 break_node.rhs = rhs;
899 try block_scope.block_node.statements.push(&break_node.base);
900 block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}");
901 const rparen = try appendToken(rp.c, .RParen, ")");
902 const grouped_expr = try rp.c.a().create(ast.Node.GroupedExpression);
903 grouped_expr.* = .{
904 .lparen = lparen,
905 .expr = &block_scope.block_node.base,
906 .rparen = rparen,
907 };
908 return maybeSuppressResult(rp, scope, result_used, &grouped_expr.base);
909 } else {
910 return maybeSuppressResult(rp, scope, result_used, rhs);
911 }
911912 },
912913 .Div => {
913914 if (!cIsUnsignedInteger(qt)) {
914915 // signed integer division uses @divTrunc
915916 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(lhs);
917 try div_trunc_node.params.push(try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value));
918918 _ = try appendToken(rp.c, .Comma, ",");
919919 const rhs = try transExpr(rp, scope, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value);
920920 try div_trunc_node.params.push(rhs);
921921 div_trunc_node.rparen_token = try appendToken(rp.c, .RParen, ")");
922922 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);
927923 }
928924 },
929925 .Rem => {
930926 if (!cIsUnsignedInteger(qt)) {
931927 // signed integer division uses @rem
932928 const rem_node = try transCreateNodeBuiltinFnCall(rp.c, "@rem");
933 const lhs = try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value);
934 try rem_node.params.push(lhs);
929 try rem_node.params.push(try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value));
935930 _ = try appendToken(rp.c, .Comma, ",");
936931 const rhs = try transExpr(rp, scope, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value);
937932 try rem_node.params.push(rhs);
938933 rem_node.rparen_token = try appendToken(rp.c, .RParen, ")");
939934 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);
944935 }
945936 },
946937 .Shl => {
947938 const node = try transCreateNodeShiftOp(rp, scope, stmt, .BitShiftLeft, .AngleBracketAngleBracketLeft, "<<");
948 return maybeSuppressResult(rp, scope, result_used, TransResult{
949 .node = node,
950 .child_scope = scope,
951 .node_scope = scope,
952 });
939 return maybeSuppressResult(rp, scope, result_used, node);
953940 },
954941 .Shr => {
955942 const node = try transCreateNodeShiftOp(rp, scope, stmt, .BitShiftRight, .AngleBracketAngleBracketRight, ">>");
956 return maybeSuppressResult(rp, scope, result_used, TransResult{
957 .node = node,
958 .child_scope = scope,
959 .node_scope = scope,
960 });
943 return maybeSuppressResult(rp, scope, result_used, node);
944 },
945 .LAnd => {
946 const node = try transCreateNodeBoolInfixOp(rp, scope, stmt, .BoolAnd, result_used, true);
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, "%");
9611000 },
9621001 .LT => {
963 const node = try transCreateNodeInfixOp(rp, scope, stmt, .LessThan, .AngleBracketLeft, "<", true);
964 return maybeSuppressResult(rp, scope, result_used, TransResult{
965 .node = node,
966 .child_scope = scope,
967 .node_scope = scope,
968 });
1002 op_id = .LessThan;
1003 op_token = try appendToken(rp.c, .AngleBracketLeft, "<");
9691004 },
9701005 .GT => {
971 const node = try transCreateNodeInfixOp(rp, scope, stmt, .GreaterThan, .AngleBracketRight, ">", true);
972 return maybeSuppressResult(rp, scope, result_used, TransResult{
973 .node = node,
974 .child_scope = scope,
975 .node_scope = scope,
976 });
1006 op_id = .GreaterThan;
1007 op_token = try appendToken(rp.c, .AngleBracketRight, ">");
9771008 },
9781009 .LE => {
979 const node = try transCreateNodeInfixOp(rp, scope, stmt, .LessOrEqual, .AngleBracketLeftEqual, "<=", true);
980 return maybeSuppressResult(rp, scope, result_used, TransResult{
981 .node = node,
982 .child_scope = scope,
983 .node_scope = scope,
984 });
1010 op_id = .LessOrEqual;
1011 op_token = try appendToken(rp.c, .AngleBracketLeftEqual, "<=");
9851012 },
9861013 .GE => {
987 const node = try transCreateNodeInfixOp(rp, scope, stmt, .GreaterOrEqual, .AngleBracketRightEqual, ">=", true);
988 return maybeSuppressResult(rp, scope, result_used, TransResult{
989 .node = node,
990 .child_scope = scope,
991 .node_scope = scope,
992 });
1014 op_id = .GreaterOrEqual;
1015 op_token = try appendToken(rp.c, .AngleBracketRightEqual, ">=");
9931016 },
9941017 .EQ => {
995 const node = try transCreateNodeInfixOp(rp, scope, stmt, .EqualEqual, .EqualEqual, "==", true);
996 return maybeSuppressResult(rp, scope, result_used, TransResult{
997 .node = node,
998 .child_scope = scope,
999 .node_scope = scope,
1000 });
1018 op_id = .EqualEqual;
1019 op_token = try appendToken(rp.c, .EqualEqual, "==");
10011020 },
10021021 .NE => {
1003 const node = try transCreateNodeInfixOp(rp, scope, stmt, .BangEqual, .BangEqual, "!=", true);
1004 return maybeSuppressResult(rp, scope, result_used, TransResult{
1005 .node = node,
1006 .child_scope = scope,
1007 .node_scope = scope,
1008 });
1022 op_id = .BangEqual;
1023 op_token = try appendToken(rp.c, .BangEqual, "!=");
10091024 },
10101025 .And => {
1011 const node = try transCreateNodeInfixOp(rp, scope, stmt, .BitAnd, .Ampersand, "&", true);
1012 return maybeSuppressResult(rp, scope, result_used, TransResult{
1013 .node = node,
1014 .child_scope = scope,
1015 .node_scope = scope,
1016 });
1026 op_id = .BitAnd;
1027 op_token = try appendToken(rp.c, .Ampersand, "&");
10171028 },
10181029 .Xor => {
1019 const node = try transCreateNodeInfixOp(rp, scope, stmt, .BitXor, .Caret, "^", true);
1020 return maybeSuppressResult(rp, scope, result_used, TransResult{
1021 .node = node,
1022 .child_scope = scope,
1023 .node_scope = scope,
1024 });
1030 op_id = .BitXor;
1031 op_token = try appendToken(rp.c, .Caret, "^");
10251032 },
10261033 .Or => {
1027 const node = try transCreateNodeInfixOp(rp, scope, stmt, .BitOr, .Pipe, "|", true);
1028 return maybeSuppressResult(rp, scope, result_used, TransResult{
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 }
1034 op_id = .BitOr;
1035 op_token = try appendToken(rp.c, .Pipe, "|");
10801036 },
1037 .Assign,
10811038 .MulAssign,
10821039 .DivAssign,
10831040 .RemAssign,
......@@ -1091,6 +1048,9 @@ fn transBinaryOperator(
10911048 => unreachable,
10921049 else => unreachable,
10931050 }
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);
10941054}
10951055
10961056fn transCompoundStmtInline(
......@@ -1231,56 +1191,22 @@ fn transImplicitCastExpr(
12311191 }
12321192}
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
12731194fn transBoolExpr(
12741195 rp: RestorePoint,
12751196 scope: *Scope,
12761197 expr: *const ZigClangExpr,
12771198 used: ResultUsed,
12781199 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;
12801206 var res = try transExpr(rp, scope, expr, used, lrvalue);
12811207
1282 switch (res.node.id) {
1283 .InfixOp => switch (@ptrCast(*const ast.Node.InfixOp, &res.node).op) {
1208 switch (res.id) {
1209 .InfixOp => switch (@fieldParentPtr(ast.Node.InfixOp, "base", res).op) {
12841210 .BoolOr,
12851211 .BoolAnd,
12861212 .EqualEqual,
......@@ -1289,24 +1215,34 @@ fn transBoolExpr(
12891215 .GreaterThan,
12901216 .LessOrEqual,
12911217 .GreaterOrEqual,
1292 => return res.node,
1218 => return res,
12931219
12941220 else => {},
12951221 },
12961222
1297 .PrefixOp => switch (@ptrCast(*const ast.Node.PrefixOp, &res.node).op) {
1298 .BoolNot => return res.node,
1223 .PrefixOp => switch (@fieldParentPtr(ast.Node.PrefixOp, "base", res).op) {
1224 .BoolNot => return res,
12991225
13001226 else => {},
13011227 },
13021228
1303 .BoolLiteral => return res.node,
1229 .BoolLiteral => return res,
13041230
13051231 else => {},
13061232 }
1307
13081233 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 {
13101246 switch (ZigClangType_getTypeClass(ty)) {
13111247 .Builtin => {
13121248 const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty);
......@@ -1337,219 +1273,48 @@ fn transBoolExpr(
13371273 .Char32,
13381274 .WChar_S,
13391275 .Float16,
1340 => return transCreateNodeNotEqual(rp, scope, res.node, try transCreateNodeInt(rp.c, 0)),
1341
1342 .NullPtr => return transCreateNodeNotEqual(rp, scope, res.node, try transCreateNodeNullLiteral(rp.c)),
1343
1344 .Void,
1345 .Half,
1346 .ObjCId,
1347 .ObjCClass,
1348 .ObjCSel,
1349 .OMPArraySection,
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
1276 => {
1277 const op_token = try appendToken(rp.c, .BangEqual, "!=");
1278 const rhs_node = try transCreateNodeInt(rp.c, 0);
1279 return transCreateNodeInfixOp(rp, scope, node, .BangEqual, op_token, rhs_node, used, grouped);
1280 },
1281 .NullPtr => {
1282 const op_token = try appendToken(rp.c, .EqualEqual, "==");
1283 const rhs_node = try transCreateNodeNullLiteral(rp.c);
1284 return transCreateNodeInfixOp(rp, scope, node, .EqualEqual, op_token, rhs_node, used, grouped);
1285 },
14361286 else => {},
14371287 }
14381288 },
1439 .Pointer => return transCreateNodeNotEqual(rp, scope, res.node, try transCreateNodeNullLiteral(rp.c)),
1440
1289 .Pointer => {
1290 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 },
14411294 .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?
1443
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 value
1445 // const typedef_ty = @ptrCast(*const ZigClangTypedefType, ty);
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);
1295 const typedef_ty = @ptrCast(*const ZigClangTypedefType, ty);
1296 const typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
1297 const underlying_type = ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl);
1298 return finishBoolExpr(rp, scope, loc, ZigClangQualType_getTypePtr(underlying_type), node, used, grouped);
14551299 },
1456
14571300 .Enum => {
1458 const gen_enum_decl_node = struct {
1459 // Have to use a callback because node must be generated inline in order to avoid weird AST printing behavior,
1460 // and the code to generate the nodes is a little different for each case
1461 fn generate_node(inner_rp: RestorePoint, enum_ty: *const struct_ZigClangType, source_loc: ZigClangSourceLocation) TransError!*ast.Node {
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 };
1301 const enum_ty = @ptrCast(*const ZigClangEnumType, ty);
1302 const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "@enumToInt");
1303 try builtin_node.params.push(node);
1304 builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
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);
14721309 },
1473
14741310 .Elaborated => {
14751311 const elaborated_ty = @ptrCast(*const ZigClangElaboratedType, ty);
1476
1477 switch (ZigClangElaboratedType_getKeyword(elaborated_ty)) {
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 }
1312 const named_type = ZigClangElaboratedType_getNamedType(elaborated_ty);
1313 return finishBoolExpr(rp, scope, loc, ZigClangQualType_getTypePtr(named_type), node, used, grouped);
15021314 },
1503
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,
1315 else => {},
15501316 }
1551
1552 unreachable;
1317 return revertAndWarn(rp, error.UnsupportedType, loc, "unsupported bool expression type", .{});
15531318}
15541319
15551320fn transIntegerLiteral(
......@@ -2036,7 +1801,6 @@ fn transSwitch(
20361801 const switch_block = try transCreateNodeBlock(rp.c, null);
20371802 try switch_block.statements.push(&switch_node.base);
20381803 switch_scope.pending_block = switch_block;
2039
20401804
20411805 const last = try transStmt(rp, &block_scope.base, ZigClangSwitchStmt_getBody(stmt), .unused, .r_value);
20421806 _ = try appendToken(rp.c, .Semicolon, ";");
......@@ -2085,7 +1849,6 @@ fn transCase(
20851849 } else
20861850 try transExpr(rp, scope, ZigClangCaseStmt_getLHS(stmt), .used, .r_value);
20871851
2088
20891852 const switch_prong = try transCreateNodeSwitchCase(rp.c, expr);
20901853 switch_prong.expr = &(try transCreateNodeBreak(rp.c, label)).base;
20911854 _ = try appendToken(rp.c, .Comma, ",");
......@@ -2271,7 +2034,7 @@ fn transConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const ZigCla
22712034 const grouped_expr = try rp.c.a().create(ast.Node.GroupedExpression);
22722035 grouped_expr.* = .{
22732036 .lparen = lparen,
2274 .expr = &if_node.base,
2037 .expr = &if_node.base,
22752038 .rparen = rparen,
22762039 };
22772040 return maybeSuppressResult(rp, scope, used, &grouped_expr.base);
......@@ -2670,87 +2433,64 @@ fn transCreateNodePrefixOp(
26702433 return node;
26712434}
26722435
2673fn transCreateNodeInfixOpImpl(
2436fn transCreateNodeInfixOp(
26742437 rp: RestorePoint,
26752438 scope: *Scope,
26762439 lhs_node: *ast.Node,
2677 rhs_node: *ast.Node,
26782440 op: ast.Node.InfixOp.Op,
2679 op_tok_id: std.zig.Token.Id,
2680 bytes: []const u8,
2441 op_token: ast.TokenIndex,
2442 rhs_node: *ast.Node,
2443 used: ResultUsed,
26812444 grouped: bool,
26822445) !*ast.Node {
2683 const lparen = if (grouped) try appendToken(rp.c, .LParen, "(") else undefined;
2684 const op_token = try appendToken(rp.c, op_tok_id, bytes);
2446 var lparen = if (grouped)
2447 try appendToken(rp.c, .LParen, "(")
2448 else
2449 null;
26852450 const node = try rp.c.a().create(ast.Node.InfixOp);
2686 node.* = ast.Node.InfixOp{
2451 node.* = .{
26872452 .op_token = op_token,
26882453 .lhs = lhs_node,
26892454 .op = op,
26902455 .rhs = rhs_node,
26912456 };
2692 if (!grouped) return &node.base;
2457 if (!grouped) return maybeSuppressResult(rp, scope, used, &node.base);
26932458 const rparen = try appendToken(rp.c, .RParen, ")");
26942459 const grouped_expr = try rp.c.a().create(ast.Node.GroupedExpression);
26952460 grouped_expr.* = .{
2696 .lparen = lparen,
2461 .lparen = lparen.?,
26972462 .expr = &node.base,
26982463 .rparen = rparen,
26992464 };
2700 return &grouped_expr.base;
2465 return maybeSuppressResult(rp, scope, used, &grouped_expr.base);
27012466}
27022467
2703fn transCreateNodeInfixOp(
2468fn transCreateNodeBoolInfixOp(
27042469 rp: RestorePoint,
27052470 scope: *Scope,
27062471 stmt: *const ZigClangBinaryOperator,
27072472 op: ast.Node.InfixOp.Op,
2708 op_tok_id: std.zig.Token.Id,
2709 bytes: []const u8,
2473 used: ResultUsed,
27102474 grouped: bool,
27112475) !*ast.Node {
2712 return transCreateNodeInfixOpImpl(
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}
2476 std.debug.assert(op == .BoolAnd or op == .BoolOr);
27322477
2733fn transCreateNodeBoolInfixOp(
2734 rp: RestorePoint,
2735 scope: *Scope,
2736 stmt: *const ZigClangBinaryOperator,
2737 comptime op: ast.Node.InfixOp.Op,
2738 comptime op_tok_id: std.zig.Token.Id,
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 }
2478 const lhs_hode = try transBoolExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value, true);
2479 const op_token = if (op == .BoolAnd)
2480 try appendToken(rp.c, .Keyword_and, "and")
2481 else
2482 try appendToken(rp.c, .Keyword_or, "or");
2483 const rhs = try transBoolExpr(rp, scope, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value, true);
27442484
2745 return transCreateNodeInfixOpImpl(
2485 return transCreateNodeInfixOp(
27462486 rp,
27472487 scope,
2748 try transBoolExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .r_value),
2749 try transBoolExpr(rp, scope, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value),
2488 lhs_hode,
27502489 op,
2751 op_tok_id,
2752 bytes,
2753 true,
2490 op_token,
2491 rhs,
2492 used,
2493 grouped,
27542494 );
27552495}
27562496
......@@ -3149,16 +2889,14 @@ fn transCreateNodeShiftOp(
31492889 comptime op_tok_id: std.zig.Token.Id,
31502890 comptime bytes: []const u8,
31512891) !*ast.Node {
3152 if (!(op == .BitShiftLeft or op == .BitShiftRight)) {
3153 @compileError("op must be either .BitShiftLeft or .BitShiftRight");
3154 }
2892 std.debug.assert(op == .BitShiftLeft or op == .BitShiftRight);
31552893
31562894 const lhs_expr = ZigClangBinaryOperator_getLHS(stmt);
31572895 const rhs_expr = ZigClangBinaryOperator_getRHS(stmt);
31582896 const rhs_location = ZigClangExpr_getBeginLoc(rhs_expr);
31592897 // 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);
31622900 const op_token = try appendToken(rp.c, op_tok_id, bytes);
31632901
31642902 const as_node = try transCreateNodeBuiltinFnCall(rp.c, "@as");
......@@ -3166,13 +2904,13 @@ fn transCreateNodeShiftOp(
31662904 try as_node.params.push(rhs_type);
31672905 _ = try appendToken(rp.c, .Comma, ",");
31682906 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);
31702908 as_node.rparen_token = try appendToken(rp.c, .RParen, ")");
31712909
31722910 const node = try rp.c.a().create(ast.Node.InfixOp);
31732911 node.* = ast.Node.InfixOp{
31742912 .op_token = op_token,
3175 .lhs = lhs.node,
2913 .lhs = lhs,
31762914 .op = op,
31772915 .rhs = &as_node.base,
31782916 };
......@@ -3648,26 +3386,26 @@ fn isZigPrimitiveType(name: []const u8) bool {
36483386 }
36493387 // void is invalid in c so it doesn't need to be checked.
36503388 return std.mem.eql(u8, name, "comptime_float") or
3651 std.mem.eql(u8, name, "comptime_int") or
3652 std.mem.eql(u8, name, "bool") or
3653 std.mem.eql(u8, name, "isize") or
3654 std.mem.eql(u8, name, "usize") or
3655 std.mem.eql(u8, name, "f16") or
3656 std.mem.eql(u8, name, "f32") or
3657 std.mem.eql(u8, name, "f64") or
3658 std.mem.eql(u8, name, "f128") or
3659 std.mem.eql(u8, name, "c_longdouble") or
3660 std.mem.eql(u8, name, "noreturn") or
3661 std.mem.eql(u8, name, "type") or
3662 std.mem.eql(u8, name, "anyerror") or
3663 std.mem.eql(u8, name, "c_short") or
3664 std.mem.eql(u8, name, "c_ushort") or
3665 std.mem.eql(u8, name, "c_int") or
3666 std.mem.eql(u8, name, "c_uint") or
3667 std.mem.eql(u8, name, "c_long") or
3668 std.mem.eql(u8, name, "c_ulong") or
3669 std.mem.eql(u8, name, "c_longlong") or
3670 std.mem.eql(u8, name, "c_ulonglong");
3389 std.mem.eql(u8, name, "comptime_int") or
3390 std.mem.eql(u8, name, "bool") or
3391 std.mem.eql(u8, name, "isize") or
3392 std.mem.eql(u8, name, "usize") or
3393 std.mem.eql(u8, name, "f16") or
3394 std.mem.eql(u8, name, "f32") or
3395 std.mem.eql(u8, name, "f64") or
3396 std.mem.eql(u8, name, "f128") or
3397 std.mem.eql(u8, name, "c_longdouble") or
3398 std.mem.eql(u8, name, "noreturn") or
3399 std.mem.eql(u8, name, "type") or
3400 std.mem.eql(u8, name, "anyerror") or
3401 std.mem.eql(u8, name, "c_short") or
3402 std.mem.eql(u8, name, "c_ushort") or
3403 std.mem.eql(u8, name, "c_int") or
3404 std.mem.eql(u8, name, "c_uint") or
3405 std.mem.eql(u8, name, "c_long") or
3406 std.mem.eql(u8, name, "c_ulong") or
3407 std.mem.eql(u8, name, "c_longlong") or
3408 std.mem.eql(u8, name, "c_ulonglong");
36713409}
36723410
36733411fn isValidZigIdentifier(name: []const u8) bool {
test/translate_c.zig+98-98
......@@ -531,33 +531,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
531531 \\}
532532 });
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
561534 cases.add_both("constant size array",
562535 \\void func(int array[20]);
563536 , &[_][]const u8{
......@@ -1388,17 +1361,109 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
13881361 \\ var h: c_int = ((a != 0) or (b != 0));
13891362 \\ var i: c_int = ((b != 0) or (c != null));
13901363 \\ 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))));
1392 \\ var l: c_int = ((@as(c_int, d) != @bitCast(enum_Foo, @as(@TagType(enum_Foo), 0))) and (b != 0));
1393 \\ var m: c_int = ((c != null) 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));
1365 \\ var l: c_int = ((@enumToInt(@as(c_uint, d)) != 0) and (b != 0));
1366 \\ var m: c_int = ((c != null) or (@enumToInt(@as(c_uint, d)) != 0));
13941367 \\ var td: SomeTypedef = 44;
13951368 \\ var o: c_int = ((td != 0) or (b != 0));
13961369 \\ var p: c_int = ((c != null) and (td != 0));
13971370 \\ return ((((((((((e + f) + g) + h) + i) + j) + k) + l) + m) + o) + p);
13981371 \\}
1372 ,
13991373 \\pub const Foo = enum_Foo;
14001374 });
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
14021467 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
14031468
14041469 cases.addAllowWarnings("simple data types",
......@@ -1525,21 +1590,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
15251590 \\ return a;
15261591 \\}
15271592 });
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
15431593 cases.addC("bitwise binary operators",
15441594 \\int max(int a, int b) {
15451595 \\ return (a & b) ^ (a | b);
......@@ -1550,20 +1600,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
15501600 \\}
15511601 });
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
15671603 cases.addC("logical and, logical or",
15681604 \\int max(int a, int b) {
15691605 \\ if (a < b || a == b)
......@@ -1580,30 +1616,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
15801616 \\}
15811617 });
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
16071619 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;`
16081620 \\enum Foo {
16091621 \\ FooA,
......@@ -1640,9 +1652,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
16401652 \\ var h: c_int = (a != 0) or (b != 0);
16411653 \\ var i: c_int = (b != 0) or (c != null);
16421654 \\ 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)));
1644 \\ var l: c_int = (@as(c_int, 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)));
1655 \\ var k: c_int = (a != 0) or (@as(c_uint, d) != @bitCast(enum_Foo, @as(@TagType(enum_Foo), 0)));
1656 \\ var l: c_int = (@as(c_uint, d) != @bitCast(enum_Foo, @as(@TagType(enum_Foo), 0))) and (b != 0);
1657 \\ var m: c_int = (c != null) or (@as(c_uint, d) != @bitCast(enum_Foo, @as(@TagType(enum_Foo), 0)));
16461658 \\ return (((((((e + f) + g) + h) + i) + j) + k) + l) + m;
16471659 \\}
16481660 });
......@@ -1760,18 +1772,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
17601772 \\}
17611773 });
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
17751775 cases.addC("compound assignment operators",
17761776 \\void foo(void) {
17771777 \\ int a = 0;