authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-17 23:28:13+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-17 23:28:13+02:00
log6d7025d0c5c619773f0f5cc49edbd30713a7328d
tree4308c25bb6d63b213dfd0306ecb6d9646f97de1d
parenta6960b89ed9b1a5951d08b1f7d8e215c86bb9e7e
signature Commit is signed but in an unrecognized format.

translate-c-2 various fixes to get more tests passing


3 files changed, 416 insertions(+), 306 deletions(-)

src-self-hosted/clang.zig+10-7
......@@ -793,16 +793,16 @@ pub extern fn ZigClangInitListExpr_getInit(self: ?*const struct_ZigClangInitList
793793pub extern fn ZigClangInitListExpr_getArrayFiller(self: ?*const struct_ZigClangInitListExpr) *const ZigClangExpr;
794794pub extern fn ZigClangInitListExpr_getNumInits(self: ?*const struct_ZigClangInitListExpr) c_uint;
795795pub extern fn ZigClangAPValue_getKind(self: ?*const struct_ZigClangAPValue) ZigClangAPValueKind;
796pub extern fn ZigClangAPValue_getInt(self: ?*const struct_ZigClangAPValue) ?*const struct_ZigClangAPSInt;
796pub extern fn ZigClangAPValue_getInt(self: ?*const struct_ZigClangAPValue) *const struct_ZigClangAPSInt;
797797pub extern fn ZigClangAPValue_getArrayInitializedElts(self: ?*const struct_ZigClangAPValue) c_uint;
798798pub extern fn ZigClangAPValue_getArraySize(self: ?*const struct_ZigClangAPValue) c_uint;
799799pub extern fn ZigClangAPValue_getLValueBase(self: ?*const struct_ZigClangAPValue) struct_ZigClangAPValueLValueBase;
800pub extern fn ZigClangAPSInt_isSigned(self: ?*const struct_ZigClangAPSInt) bool;
801pub extern fn ZigClangAPSInt_isNegative(self: ?*const struct_ZigClangAPSInt) bool;
802pub extern fn ZigClangAPSInt_negate(self: ?*const struct_ZigClangAPSInt) ?*const struct_ZigClangAPSInt;
803pub extern fn ZigClangAPSInt_free(self: ?*const struct_ZigClangAPSInt) void;
804pub extern fn ZigClangAPSInt_getRawData(self: ?*const struct_ZigClangAPSInt) [*:0]const u64;
805pub extern fn ZigClangAPSInt_getNumWords(self: ?*const struct_ZigClangAPSInt) c_uint;
800pub extern fn ZigClangAPSInt_isSigned(self: *const struct_ZigClangAPSInt) bool;
801pub extern fn ZigClangAPSInt_isNegative(self: *const struct_ZigClangAPSInt) bool;
802pub extern fn ZigClangAPSInt_negate(self: *const struct_ZigClangAPSInt) *const struct_ZigClangAPSInt;
803pub extern fn ZigClangAPSInt_free(self: *const struct_ZigClangAPSInt) void;
804pub extern fn ZigClangAPSInt_getRawData(self: *const struct_ZigClangAPSInt) [*:0]const u64;
805pub extern fn ZigClangAPSInt_getNumWords(self: *const struct_ZigClangAPSInt) c_uint;
806806
807807pub extern fn ZigClangAPInt_getLimitedValue(self: *const struct_ZigClangAPInt, limit: u64) u64;
808808pub extern fn ZigClangAPValueLValueBase_dyn_cast_Expr(self: struct_ZigClangAPValueLValueBase) ?*const struct_ZigClangExpr;
......@@ -1074,3 +1074,6 @@ pub extern fn ZigClangCaseStmt_getSubStmt(*const ZigClangCaseStmt) *const ZigCla
10741074pub extern fn ZigClangDefaultStmt_getSubStmt(*const ZigClangDefaultStmt) *const ZigClangStmt;
10751075
10761076pub extern fn ZigClangExpr_EvaluateAsConstantExpr(*const ZigClangExpr, *ZigClangExprEvalResult, ZigClangExpr_ConstExprUsage, *const ZigClangASTContext) bool;
1077
1078pub extern fn ZigClangPredefinedExpr_getFunctionName(*const ZigClangPredefinedExpr) *const ZigClangStringLiteral;
1079
src-self-hosted/translate_c.zig+17-4
......@@ -861,6 +861,7 @@ fn transStmt(
861861 .CaseStmtClass => return transCase(rp, scope, @ptrCast(*const ZigClangCaseStmt, stmt)),
862862 .DefaultStmtClass => return transDefault(rp, scope, @ptrCast(*const ZigClangDefaultStmt, stmt)),
863863 .ConstantExprClass => return transConstantExpr(rp, scope, @ptrCast(*const ZigClangExpr, stmt), result_used),
864 .PredefinedExprClass => return transPredefinedExpr(rp, scope, @ptrCast(*const ZigClangPredefinedExpr, stmt), result_used),
864865 else => {
865866 return revertAndWarn(
866867 rp,
......@@ -1748,6 +1749,10 @@ fn transConstantExpr(rp: RestorePoint, scope: *Scope, expr: *const ZigClangExpr,
17481749 return maybeSuppressResult(rp, scope, used, try transCreateNodeAPInt(rp.c, ZigClangAPValue_getInt(&result.Val)));
17491750}
17501751
1752fn transPredefinedExpr(rp: RestorePoint, scope: *Scope, expr: *const ZigClangPredefinedExpr, used: ResultUsed) TransError!*ast.Node {
1753 return transStringLiteral(rp, scope, ZigClangPredefinedExpr_getFunctionName(expr), used);
1754}
1755
17511756fn transCPtrCast(
17521757 rp: RestorePoint,
17531758 loc: ZigClangSourceLocation,
......@@ -2191,11 +2196,17 @@ fn transCreateNodePtrType(
21912196 return node;
21922197}
21932198
2194fn transCreateNodeAPInt(c: *Context, int: ?*const ZigClangAPSInt) !*ast.Node {
2195 const num_limbs = ZigClangAPSInt_getNumWords(int.?);
2199fn transCreateNodeAPInt(c: *Context, int: *const ZigClangAPSInt) !*ast.Node {
2200 const num_limbs = ZigClangAPSInt_getNumWords(int);
2201 var aps_int = int;
2202 const is_negative = ZigClangAPSInt_isSigned(int) and ZigClangAPSInt_isNegative(int);
2203 if (is_negative)
2204 aps_int = ZigClangAPSInt_negate(aps_int);
21962205 var big = try std.math.big.Int.initCapacity(c.a(), num_limbs);
2206 if (is_negative)
2207 big.negate();
21972208 defer big.deinit();
2198 const data = ZigClangAPSInt_getRawData(int.?);
2209 const data = ZigClangAPSInt_getRawData(aps_int);
21992210 var i: @TypeOf(num_limbs) = 0;
22002211 while (i < num_limbs) : (i += 1) big.limbs[i] = data[i];
22012212 const str = big.toString(c.a(), 10) catch |err| switch (err) {
......@@ -2207,6 +2218,8 @@ fn transCreateNodeAPInt(c: *Context, int: ?*const ZigClangAPSInt) !*ast.Node {
22072218 node.* = .{
22082219 .token = token,
22092220 };
2221 if (is_negative)
2222 ZigClangAPSInt_free(aps_int);
22102223 return &node.base;
22112224}
22122225
......@@ -2803,7 +2816,7 @@ fn finishTransFnProto(
28032816 const param = ZigClangFunctionDecl_getParamDecl(fn_decl.?, @intCast(c_uint, i));
28042817 var param_name: []const u8 = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, param)));
28052818 if (param_name.len < 1)
2806 param_name = "arg"[0..];
2819 param_name = try std.fmt.allocPrint(rp.c.a(), "arg_{}", .{rp.c.getMangle()});
28072820 const checked_param_name = if (try scope.createAlias(rp.c, param_name)) |a| blk: {
28082821 try fndef_scope.params.push(.{ .name = param_name, .alias = a });
28092822 break :blk a;
test/translate_c.zig+389-295
......@@ -426,6 +426,180 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
426426 },
427427 );
428428
429 cases.addC_both("null statements",
430 \\void foo(void) {
431 \\ ;;;;;
432 \\}
433 , &[_][]const u8{
434 \\pub export fn foo() void {
435 \\ {}
436 \\ {}
437 \\ {}
438 \\ {}
439 \\ {}
440 \\}
441 });
442
443 if (builtin.os != builtin.Os.windows) {
444 // Windows treats this as an enum with type c_int
445 cases.add_both("big negative enum init values when C ABI supports long long enums",
446 \\enum EnumWithInits {
447 \\ VAL01 = 0,
448 \\ VAL02 = 1,
449 \\ VAL03 = 2,
450 \\ VAL04 = 3,
451 \\ VAL05 = -1,
452 \\ VAL06 = -2,
453 \\ VAL07 = -3,
454 \\ VAL08 = -4,
455 \\ VAL09 = VAL02 + VAL08,
456 \\ VAL10 = -1000012000,
457 \\ VAL11 = -1000161000,
458 \\ VAL12 = -1000174001,
459 \\ VAL13 = VAL09,
460 \\ VAL14 = VAL10,
461 \\ VAL15 = VAL11,
462 \\ VAL16 = VAL13,
463 \\ VAL17 = (VAL16 - VAL10 + 1),
464 \\ VAL18 = 0x1000000000000000L,
465 \\ VAL19 = VAL18 + VAL18 + VAL18 - 1,
466 \\ VAL20 = VAL19 + VAL19,
467 \\ VAL21 = VAL20 + 0xFFFFFFFFFFFFFFFF,
468 \\ VAL22 = 0xFFFFFFFFFFFFFFFF + 1,
469 \\ VAL23 = 0xFFFFFFFFFFFFFFFF,
470 \\};
471 , &[_][]const u8{
472 \\pub const enum_EnumWithInits = extern enum(c_longlong) {
473 \\ VAL01 = 0,
474 \\ VAL02 = 1,
475 \\ VAL03 = 2,
476 \\ VAL04 = 3,
477 \\ VAL05 = -1,
478 \\ VAL06 = -2,
479 \\ VAL07 = -3,
480 \\ VAL08 = -4,
481 \\ VAL09 = -3,
482 \\ VAL10 = -1000012000,
483 \\ VAL11 = -1000161000,
484 \\ VAL12 = -1000174001,
485 \\ VAL13 = -3,
486 \\ VAL14 = -1000012000,
487 \\ VAL15 = -1000161000,
488 \\ VAL16 = -3,
489 \\ VAL17 = 1000011998,
490 \\ VAL18 = 1152921504606846976,
491 \\ VAL19 = 3458764513820540927,
492 \\ VAL20 = 6917529027641081854,
493 \\ VAL21 = 6917529027641081853,
494 \\ VAL22 = 0,
495 \\ VAL23 = -1,
496 \\};
497 });
498 }
499
500 cases.addC_both("predefined expressions",
501 \\void foo(void) {
502 \\ __func__;
503 \\ __FUNCTION__;
504 \\ __PRETTY_FUNCTION__;
505 \\}
506 , &[_][]const u8{
507 \\pub export fn foo() void {
508 \\ _ = "foo";
509 \\ _ = "foo";
510 \\ _ = "void foo(void)";
511 \\}
512 });
513
514 cases.addC_both("ignore result, no function arguments",
515 \\void foo() {
516 \\ int a;
517 \\ 1;
518 \\ "hey";
519 \\ 1 + 1;
520 \\ 1 - 1;
521 \\ a = 1;
522 \\}
523 , &[_][]const u8{
524 \\pub export fn foo() void {
525 \\ var a: c_int = undefined;
526 \\ _ = 1;
527 \\ _ = "hey";
528 \\ _ = (1 + 1);
529 \\ _ = (1 - 1);
530 \\ a = 1;
531 \\}
532 });
533
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",
562 \\void func(int array[20]);
563 , &[_][]const u8{
564 \\pub extern fn func(array: [*c]c_int) void;
565 });
566
567 cases.add_both("__cdecl doesn't mess up function pointers",
568 \\void foo(void (__cdecl *fn_ptr)(void));
569 , &[_][]const u8{
570 \\pub extern fn foo(fn_ptr: ?extern fn () void) void;
571 });
572
573 cases.addC_both("void cast",
574 \\void foo(int a) {
575 \\ (void) a;
576 \\}
577 , &[_][]const u8{
578 \\pub export fn foo(a: c_int) void {
579 \\ _ = a;
580 \\}
581 });
582
583 cases.addC_both("implicit cast to void *",
584 \\void *foo(unsigned short *x) {
585 \\ return x;
586 \\}
587 , &[_][]const u8{
588 \\pub export fn foo(x: [*c]c_ushort) ?*c_void {
589 \\ return @ptrCast(?*c_void, x);
590 \\}
591 });
592
593 cases.addC_both("null pointer implicit cast",
594 \\int* foo(void) {
595 \\ return 0;
596 \\}
597 , &[_][]const u8{
598 \\pub export fn foo() [*c]c_int {
599 \\ return null;
600 \\}
601 });
602
429603 /////////////// Cases that pass for only stage2 ////////////////
430604
431605 cases.add_2("Parameterless function prototypes",
......@@ -904,145 +1078,75 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
9041078 \\};
9051079 });
9061080
907 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
908
909 if (builtin.os != builtin.Os.windows) {
910 // Windows treats this as an enum with type c_int
911 cases.add("big negative enum init values when C ABI supports long long enums",
912 \\enum EnumWithInits {
913 \\ VAL01 = 0,
914 \\ VAL02 = 1,
915 \\ VAL03 = 2,
916 \\ VAL04 = 3,
917 \\ VAL05 = -1,
918 \\ VAL06 = -2,
919 \\ VAL07 = -3,
920 \\ VAL08 = -4,
921 \\ VAL09 = VAL02 + VAL08,
922 \\ VAL10 = -1000012000,
923 \\ VAL11 = -1000161000,
924 \\ VAL12 = -1000174001,
925 \\ VAL13 = VAL09,
926 \\ VAL14 = VAL10,
927 \\ VAL15 = VAL11,
928 \\ VAL16 = VAL13,
929 \\ VAL17 = (VAL16 - VAL10 + 1),
930 \\ VAL18 = 0x1000000000000000L,
931 \\ VAL19 = VAL18 + VAL18 + VAL18 - 1,
932 \\ VAL20 = VAL19 + VAL19,
933 \\ VAL21 = VAL20 + 0xFFFFFFFFFFFFFFFF,
934 \\ VAL22 = 0xFFFFFFFFFFFFFFFF + 1,
935 \\ VAL23 = 0xFFFFFFFFFFFFFFFF,
936 \\};
937 , &[_][]const u8{
938 \\pub const enum_EnumWithInits = extern enum(c_longlong) {
939 \\ VAL01 = 0,
940 \\ VAL02 = 1,
941 \\ VAL03 = 2,
942 \\ VAL04 = 3,
943 \\ VAL05 = -1,
944 \\ VAL06 = -2,
945 \\ VAL07 = -3,
946 \\ VAL08 = -4,
947 \\ VAL09 = -3,
948 \\ VAL10 = -1000012000,
949 \\ VAL11 = -1000161000,
950 \\ VAL12 = -1000174001,
951 \\ VAL13 = -3,
952 \\ VAL14 = -1000012000,
953 \\ VAL15 = -1000161000,
954 \\ VAL16 = -3,
955 \\ VAL17 = 1000011998,
956 \\ VAL18 = 1152921504606846976,
957 \\ VAL19 = 3458764513820540927,
958 \\ VAL20 = 6917529027641081854,
959 \\ VAL21 = 6917529027641081853,
960 \\ VAL22 = 0,
961 \\ VAL23 = -1,
962 \\};
963 });
964 }
965
966 cases.add("predefined expressions",
967 \\void foo(void) {
968 \\ __func__;
969 \\ __FUNCTION__;
970 \\ __PRETTY_FUNCTION__;
971 \\}
1081 cases.add_2("undefined array global",
1082 \\int array[100] = {};
9721083 , &[_][]const u8{
973 \\pub fn foo() void {
974 \\ _ = "foo";
975 \\ _ = "foo";
976 \\ _ = "void foo(void)";
977 \\}
1084 \\pub export var array: [100]c_int = .{0} ** 100;
9781085 });
9791086
980 cases.add("ignore result, no function arguments",
981 \\void foo() {
982 \\ int a;
983 \\ 1;
984 \\ "hey";
985 \\ 1 + 1;
986 \\ 1 - 1;
987 \\ a = 1;
988 \\}
1087 cases.add_2("restrict -> noalias",
1088 \\void foo(void *restrict bar, void *restrict);
9891089 , &[_][]const u8{
990 \\pub fn foo() void {
991 \\ var a: c_int = undefined;
992 \\ _ = 1;
993 \\ _ = "hey";
994 \\ _ = (1 + 1);
995 \\ _ = (1 - 1);
996 \\ a = 1;
997 \\}
1090 \\pub extern fn foo(noalias bar: ?*c_void, noalias arg_1: ?*c_void) void;
9981091 });
9991092
1000 cases.add("for loop with var init but empty body",
1001 \\void foo(void) {
1002 \\ for (int x = 0; x < 10; x++);
1093 cases.add_2("assign",
1094 \\int max(int a) {
1095 \\ int tmp;
1096 \\ tmp = a;
1097 \\ a = tmp;
10031098 \\}
10041099 , &[_][]const u8{
1005 \\pub fn foo() void {
1006 \\ {
1007 \\ var x: c_int = 0;
1008 \\ while (x < 10) : (x += 1) {}
1009 \\ }
1100 \\pub export fn max(a: c_int) c_int {
1101 \\ var tmp: c_int = undefined;
1102 \\ tmp = a;
1103 \\ a = tmp;
10101104 \\}
10111105 });
10121106
1013 cases.add("do while with empty body",
1014 \\void foo(void) {
1015 \\ do ; while (1);
1107 cases.add_2("chaining assign",
1108 \\void max(int a) {
1109 \\ int b, c;
1110 \\ c = b = a;
10161111 \\}
1017 , &[_][]const u8{ // TODO this should be if (1 != 0) break
1018 \\pub fn foo() void {
1019 \\ while (true) {
1020 \\ {}
1021 \\ if (!1) break;
1022 \\ }
1112 , &[_][]const u8{
1113 \\pub export fn max(a: c_int) void {
1114 \\ var b: c_int = undefined;
1115 \\ var c: c_int = undefined;
1116 \\ c = blk: {
1117 \\ const _tmp_1 = a;
1118 \\ b = _tmp_1;
1119 \\ break :blk _tmp_1;
1120 \\ };
10231121 \\}
10241122 });
10251123
1026 cases.add("for with empty body",
1027 \\void foo(void) {
1028 \\ for (;;);
1029 \\}
1124 cases.add_2("anonymous enum",
1125 \\enum {
1126 \\ One,
1127 \\ Two,
1128 \\};
10301129 , &[_][]const u8{
1031 \\pub fn foo() void {
1032 \\ while (true) {}
1033 \\}
1130 \\pub const One = enum_unnamed_1.One;
1131 \\pub const Two = enum_unnamed_1.Two;
1132 \\pub const enum_unnamed_1 = extern enum {
1133 \\ One,
1134 \\ Two,
1135 \\};
10341136 });
10351137
1036 cases.add("while with empty body",
1037 \\void foo(void) {
1038 \\ while (1);
1138 cases.add_2("c style cast",
1139 \\int float_to_int(float a) {
1140 \\ return (int)a;
10391141 \\}
10401142 , &[_][]const u8{
1041 \\pub fn foo() void {
1042 \\ while (1 != 0) {}
1143 \\pub export fn float_to_int(a: f32) c_int {
1144 \\ return @floatToInt(c_int, a);
10431145 \\}
10441146 });
10451147
1148 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
1149
10461150 cases.addAllowWarnings("simple data types",
10471151 \\#include <stdint.h>
10481152 \\int foo(char a, unsigned char b, signed char c);
......@@ -1067,56 +1171,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
10671171 \\}
10681172 });
10691173
1070 cases.add("restrict -> noalias",
1071 \\void foo(void *restrict bar, void *restrict);
1072 , &[_][]const u8{
1073 \\pub extern fn foo(noalias bar: ?*c_void, noalias arg1: ?*c_void) void;
1074 });
1075
1076 cases.add("qualified struct and enum",
1077 \\struct Foo {
1078 \\ int x;
1079 \\ int y;
1080 \\};
1081 \\enum Bar {
1082 \\ BarA,
1083 \\ BarB,
1084 \\};
1085 \\void func(struct Foo *a, enum Bar **b);
1086 , &[_][]const u8{
1087 \\pub const struct_Foo = extern struct {
1088 \\ x: c_int,
1089 \\ y: c_int,
1090 \\};
1091 ,
1092 \\pub const enum_Bar = extern enum {
1093 \\ A,
1094 \\ B,
1095 \\};
1096 ,
1097 \\pub const BarA = enum_Bar.A;
1098 ,
1099 \\pub const BarB = enum_Bar.B;
1100 ,
1101 \\pub extern fn func(a: [*c]struct_Foo, b: [*c]([*c]enum_Bar)) void;
1102 ,
1103 \\pub const Foo = struct_Foo;
1104 ,
1105 \\pub const Bar = enum_Bar;
1106 });
1107
1108 cases.add("constant size array",
1109 \\void func(int array[20]);
1110 , &[_][]const u8{
1111 \\pub extern fn func(array: [*c]c_int) void;
1112 });
1113
1114 cases.add("__cdecl doesn't mess up function pointers",
1115 \\void foo(void (__cdecl *fn_ptr)(void));
1116 , &[_][]const u8{
1117 \\pub extern fn foo(fn_ptr: ?extern fn () void) void;
1118 });
1119
11201174 cases.add("macro defines string literal with hex",
11211175 \\#define FOO "aoeu\xab derp"
11221176 \\#define FOO2 "aoeu\x0007a derp"
......@@ -1247,54 +1301,22 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
12471301 cases.addC("logical and, logical or on none bool values",
12481302 \\int and_or_none_bool(int a, float b, void *c) {
12491303 \\ if (a && b) return 0;
1250 \\ if (b && c) return 1;
1251 \\ if (a && c) return 2;
1252 \\ if (a || b) return 3;
1253 \\ if (b || c) return 4;
1254 \\ if (a || c) return 5;
1255 \\ return 6;
1256 \\}
1257 , &[_][]const u8{
1258 \\pub export fn and_or_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
1259 \\ if ((a != 0) and (b != 0)) return 0;
1260 \\ if ((b != 0) and (c != null)) return 1;
1261 \\ if ((a != 0) and (c != null)) return 2;
1262 \\ if ((a != 0) or (b != 0)) return 3;
1263 \\ if ((b != 0) or (c != null)) return 4;
1264 \\ if ((a != 0) or (c != null)) return 5;
1265 \\ return 6;
1266 \\}
1267 });
1268
1269 cases.addC("assign",
1270 \\int max(int a) {
1271 \\ int tmp;
1272 \\ tmp = a;
1273 \\ a = tmp;
1274 \\}
1275 , &[_][]const u8{
1276 \\pub export fn max(_arg_a: c_int) c_int {
1277 \\ var a = _arg_a;
1278 \\ var tmp: c_int = undefined;
1279 \\ tmp = a;
1280 \\ a = tmp;
1281 \\}
1282 });
1283
1284 cases.addC("chaining assign",
1285 \\void max(int a) {
1286 \\ int b, c;
1287 \\ c = b = a;
1304 \\ if (b && c) return 1;
1305 \\ if (a && c) return 2;
1306 \\ if (a || b) return 3;
1307 \\ if (b || c) return 4;
1308 \\ if (a || c) return 5;
1309 \\ return 6;
12881310 \\}
12891311 , &[_][]const u8{
1290 \\pub export fn max(a: c_int) void {
1291 \\ var b: c_int = undefined;
1292 \\ var c: c_int = undefined;
1293 \\ c = (x: {
1294 \\ const _tmp = a;
1295 \\ b = _tmp;
1296 \\ break :x _tmp;
1297 \\ });
1312 \\pub export fn and_or_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
1313 \\ if ((a != 0) and (b != 0)) return 0;
1314 \\ if ((b != 0) and (c != null)) return 1;
1315 \\ if ((a != 0) and (c != null)) return 2;
1316 \\ if ((a != 0) or (b != 0)) return 3;
1317 \\ if ((b != 0) or (c != null)) return 4;
1318 \\ if ((a != 0) or (c != null)) return 5;
1319 \\ return 6;
12981320 \\}
12991321 });
13001322
......@@ -1318,16 +1340,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
13181340 \\}
13191341 });
13201342
1321 cases.add("anonymous enum",
1322 \\enum {
1323 \\ One,
1324 \\ Two,
1325 \\};
1326 , &[_][]const u8{
1327 \\pub const One = 0;
1328 \\pub const Two = 1;
1329 });
1330
13311343 cases.addC("function call",
13321344 \\static void bar(void) { }
13331345 \\static int baz(void) { return 0; }
......@@ -1362,26 +1374,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
13621374 \\}
13631375 });
13641376
1365 cases.addC("null statements",
1366 \\void foo(void) {
1367 \\ ;;;;;
1368 \\}
1369 , &[_][]const u8{
1370 \\pub export fn foo() void {
1371 \\ {}
1372 \\ {}
1373 \\ {}
1374 \\ {}
1375 \\ {}
1376 \\}
1377 });
1378
1379 cases.add("undefined array global",
1380 \\int array[100];
1381 , &[_][]const u8{
1382 \\pub var array: [100]c_int = undefined;
1383 });
1384
13851377 cases.addC("array access",
13861378 \\int array[100];
13871379 \\int foo(int index) {
......@@ -1394,36 +1386,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
13941386 \\}
13951387 });
13961388
1397 cases.addC("c style cast",
1398 \\int float_to_int(float a) {
1399 \\ return (int)a;
1400 \\}
1401 , &[_][]const u8{
1402 \\pub export fn float_to_int(a: f32) c_int {
1403 \\ return @as(c_int, a);
1404 \\}
1405 });
1406
1407 cases.addC("void cast",
1408 \\void foo(int a) {
1409 \\ (void) a;
1410 \\}
1411 , &[_][]const u8{
1412 \\pub export fn foo(a: c_int) void {
1413 \\ _ = a;
1414 \\}
1415 });
1416
1417 cases.addC("implicit cast to void *",
1418 \\void *foo(unsigned short *x) {
1419 \\ return x;
1420 \\}
1421 , &[_][]const u8{
1422 \\pub export fn foo(x: [*c]c_ushort) ?*c_void {
1423 \\ return @ptrCast(?*c_void, x);
1424 \\}
1425 });
1426
14271389 cases.addC("sizeof",
14281390 \\#include <stddef.h>
14291391 \\size_t size_of(void) {
......@@ -1435,29 +1397,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
14351397 \\}
14361398 });
14371399
1438 cases.addC("null pointer implicit cast",
1439 \\int* foo(void) {
1440 \\ return 0;
1441 \\}
1442 , &[_][]const u8{
1443 \\pub export fn foo() [*c]c_int {
1444 \\ return null;
1445 \\}
1446 });
1447
1448 cases.addC("comma operator",
1449 \\int foo(void) {
1450 \\ return 1, 2;
1451 \\}
1452 , &[_][]const u8{
1453 \\pub export fn foo() c_int {
1454 \\ return x: {
1455 \\ _ = 1;
1456 \\ break :x 2;
1457 \\ };
1458 \\}
1459 });
1460
14611400 cases.addC("statement expression",
14621401 \\int foo(void) {
14631402 \\ return ({
......@@ -2292,4 +2231,159 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
22922231 \\ }
22932232 \\}
22942233 });
2234
2235 cases.add("for loop with var init but empty body",
2236 \\void foo(void) {
2237 \\ for (int x = 0; x < 10; x++);
2238 \\}
2239 , &[_][]const u8{
2240 \\pub fn foo() void {
2241 \\ {
2242 \\ var x: c_int = 0;
2243 \\ while (x < 10) : (x += 1) {}
2244 \\ }
2245 \\}
2246 });
2247
2248 cases.add("do while with empty body",
2249 \\void foo(void) {
2250 \\ do ; while (1);
2251 \\}
2252 , &[_][]const u8{ // TODO this should be if (1 != 0) break
2253 \\pub fn foo() void {
2254 \\ while (true) {
2255 \\ {}
2256 \\ if (!1) break;
2257 \\ }
2258 \\}
2259 });
2260
2261 cases.add("for with empty body",
2262 \\void foo(void) {
2263 \\ for (;;);
2264 \\}
2265 , &[_][]const u8{
2266 \\pub fn foo() void {
2267 \\ while (true) {}
2268 \\}
2269 });
2270
2271 cases.add("while with empty body",
2272 \\void foo(void) {
2273 \\ while (1);
2274 \\}
2275 , &[_][]const u8{
2276 \\pub fn foo() void {
2277 \\ while (1 != 0) {}
2278 \\}
2279 });
2280
2281 cases.add("undefined array global",
2282 \\int array[100];
2283 , &[_][]const u8{
2284 \\pub var array: [100]c_int = undefined;
2285 });
2286
2287 cases.add("qualified struct and enum",
2288 \\struct Foo {
2289 \\ int x;
2290 \\ int y;
2291 \\};
2292 \\enum Bar {
2293 \\ BarA,
2294 \\ BarB,
2295 \\};
2296 \\void func(struct Foo *a, enum Bar **b);
2297 , &[_][]const u8{
2298 \\pub const struct_Foo = extern struct {
2299 \\ x: c_int,
2300 \\ y: c_int,
2301 \\};
2302 ,
2303 \\pub const enum_Bar = extern enum {
2304 \\ A,
2305 \\ B,
2306 \\};
2307 ,
2308 \\pub const BarA = enum_Bar.A;
2309 ,
2310 \\pub const BarB = enum_Bar.B;
2311 ,
2312 \\pub extern fn func(a: [*c]struct_Foo, b: [*c]([*c]enum_Bar)) void;
2313 ,
2314 \\pub const Foo = struct_Foo;
2315 ,
2316 \\pub const Bar = enum_Bar;
2317 });
2318
2319 cases.add("restrict -> noalias",
2320 \\void foo(void *restrict bar, void *restrict);
2321 , &[_][]const u8{
2322 \\pub extern fn foo(noalias bar: ?*c_void, noalias arg1: ?*c_void) void;
2323 });
2324
2325 cases.addC("assign",
2326 \\int max(int a) {
2327 \\ int tmp;
2328 \\ tmp = a;
2329 \\ a = tmp;
2330 \\}
2331 , &[_][]const u8{
2332 \\pub export fn max(_arg_a: c_int) c_int {
2333 \\ var a = _arg_a;
2334 \\ var tmp: c_int = undefined;
2335 \\ tmp = a;
2336 \\ a = tmp;
2337 \\}
2338 });
2339
2340 cases.addC("chaining assign",
2341 \\void max(int a) {
2342 \\ int b, c;
2343 \\ c = b = a;
2344 \\}
2345 , &[_][]const u8{
2346 \\pub export fn max(a: c_int) void {
2347 \\ var b: c_int = undefined;
2348 \\ var c: c_int = undefined;
2349 \\ c = (x: {
2350 \\ const _tmp = a;
2351 \\ b = _tmp;
2352 \\ break :x _tmp;
2353 \\ });
2354 \\}
2355 });
2356
2357 cases.add("anonymous enum",
2358 \\enum {
2359 \\ One,
2360 \\ Two,
2361 \\};
2362 , &[_][]const u8{
2363 \\pub const One = 0;
2364 \\pub const Two = 1;
2365 });
2366
2367 cases.addC("c style cast",
2368 \\int float_to_int(float a) {
2369 \\ return (int)a;
2370 \\}
2371 , &[_][]const u8{
2372 \\pub export fn float_to_int(a: f32) c_int {
2373 \\ return @as(c_int, a);
2374 \\}
2375 });
2376
2377 cases.addC("comma operator",
2378 \\int foo(void) {
2379 \\ return 1, 2;
2380 \\}
2381 , &[_][]const u8{
2382 \\pub export fn foo() c_int {
2383 \\ return x: {
2384 \\ _ = 1;
2385 \\ break :x 2;
2386 \\ };
2387 \\}
2388 });
22952389}