mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 16:54:52 +00:00
translate-c-2 various fixes to get more tests passing
This commit is contained in:
parent
a6960b89ed
commit
6d7025d0c5
@ -793,16 +793,16 @@ pub extern fn ZigClangInitListExpr_getInit(self: ?*const struct_ZigClangInitList
|
||||
pub extern fn ZigClangInitListExpr_getArrayFiller(self: ?*const struct_ZigClangInitListExpr) *const ZigClangExpr;
|
||||
pub extern fn ZigClangInitListExpr_getNumInits(self: ?*const struct_ZigClangInitListExpr) c_uint;
|
||||
pub extern fn ZigClangAPValue_getKind(self: ?*const struct_ZigClangAPValue) ZigClangAPValueKind;
|
||||
pub extern fn ZigClangAPValue_getInt(self: ?*const struct_ZigClangAPValue) ?*const struct_ZigClangAPSInt;
|
||||
pub extern fn ZigClangAPValue_getInt(self: ?*const struct_ZigClangAPValue) *const struct_ZigClangAPSInt;
|
||||
pub extern fn ZigClangAPValue_getArrayInitializedElts(self: ?*const struct_ZigClangAPValue) c_uint;
|
||||
pub extern fn ZigClangAPValue_getArraySize(self: ?*const struct_ZigClangAPValue) c_uint;
|
||||
pub extern fn ZigClangAPValue_getLValueBase(self: ?*const struct_ZigClangAPValue) struct_ZigClangAPValueLValueBase;
|
||||
pub extern fn ZigClangAPSInt_isSigned(self: ?*const struct_ZigClangAPSInt) bool;
|
||||
pub extern fn ZigClangAPSInt_isNegative(self: ?*const struct_ZigClangAPSInt) bool;
|
||||
pub extern fn ZigClangAPSInt_negate(self: ?*const struct_ZigClangAPSInt) ?*const struct_ZigClangAPSInt;
|
||||
pub extern fn ZigClangAPSInt_free(self: ?*const struct_ZigClangAPSInt) void;
|
||||
pub extern fn ZigClangAPSInt_getRawData(self: ?*const struct_ZigClangAPSInt) [*:0]const u64;
|
||||
pub extern fn ZigClangAPSInt_getNumWords(self: ?*const struct_ZigClangAPSInt) c_uint;
|
||||
pub extern fn ZigClangAPSInt_isSigned(self: *const struct_ZigClangAPSInt) bool;
|
||||
pub extern fn ZigClangAPSInt_isNegative(self: *const struct_ZigClangAPSInt) bool;
|
||||
pub extern fn ZigClangAPSInt_negate(self: *const struct_ZigClangAPSInt) *const struct_ZigClangAPSInt;
|
||||
pub extern fn ZigClangAPSInt_free(self: *const struct_ZigClangAPSInt) void;
|
||||
pub extern fn ZigClangAPSInt_getRawData(self: *const struct_ZigClangAPSInt) [*:0]const u64;
|
||||
pub extern fn ZigClangAPSInt_getNumWords(self: *const struct_ZigClangAPSInt) c_uint;
|
||||
|
||||
pub extern fn ZigClangAPInt_getLimitedValue(self: *const struct_ZigClangAPInt, limit: u64) u64;
|
||||
pub 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
|
||||
pub extern fn ZigClangDefaultStmt_getSubStmt(*const ZigClangDefaultStmt) *const ZigClangStmt;
|
||||
|
||||
pub extern fn ZigClangExpr_EvaluateAsConstantExpr(*const ZigClangExpr, *ZigClangExprEvalResult, ZigClangExpr_ConstExprUsage, *const ZigClangASTContext) bool;
|
||||
|
||||
pub extern fn ZigClangPredefinedExpr_getFunctionName(*const ZigClangPredefinedExpr) *const ZigClangStringLiteral;
|
||||
|
||||
|
||||
@ -861,6 +861,7 @@ fn transStmt(
|
||||
.CaseStmtClass => return transCase(rp, scope, @ptrCast(*const ZigClangCaseStmt, stmt)),
|
||||
.DefaultStmtClass => return transDefault(rp, scope, @ptrCast(*const ZigClangDefaultStmt, stmt)),
|
||||
.ConstantExprClass => return transConstantExpr(rp, scope, @ptrCast(*const ZigClangExpr, stmt), result_used),
|
||||
.PredefinedExprClass => return transPredefinedExpr(rp, scope, @ptrCast(*const ZigClangPredefinedExpr, stmt), result_used),
|
||||
else => {
|
||||
return revertAndWarn(
|
||||
rp,
|
||||
@ -1748,6 +1749,10 @@ fn transConstantExpr(rp: RestorePoint, scope: *Scope, expr: *const ZigClangExpr,
|
||||
return maybeSuppressResult(rp, scope, used, try transCreateNodeAPInt(rp.c, ZigClangAPValue_getInt(&result.Val)));
|
||||
}
|
||||
|
||||
fn transPredefinedExpr(rp: RestorePoint, scope: *Scope, expr: *const ZigClangPredefinedExpr, used: ResultUsed) TransError!*ast.Node {
|
||||
return transStringLiteral(rp, scope, ZigClangPredefinedExpr_getFunctionName(expr), used);
|
||||
}
|
||||
|
||||
fn transCPtrCast(
|
||||
rp: RestorePoint,
|
||||
loc: ZigClangSourceLocation,
|
||||
@ -2191,11 +2196,17 @@ fn transCreateNodePtrType(
|
||||
return node;
|
||||
}
|
||||
|
||||
fn transCreateNodeAPInt(c: *Context, int: ?*const ZigClangAPSInt) !*ast.Node {
|
||||
const num_limbs = ZigClangAPSInt_getNumWords(int.?);
|
||||
fn transCreateNodeAPInt(c: *Context, int: *const ZigClangAPSInt) !*ast.Node {
|
||||
const num_limbs = ZigClangAPSInt_getNumWords(int);
|
||||
var aps_int = int;
|
||||
const is_negative = ZigClangAPSInt_isSigned(int) and ZigClangAPSInt_isNegative(int);
|
||||
if (is_negative)
|
||||
aps_int = ZigClangAPSInt_negate(aps_int);
|
||||
var big = try std.math.big.Int.initCapacity(c.a(), num_limbs);
|
||||
if (is_negative)
|
||||
big.negate();
|
||||
defer big.deinit();
|
||||
const data = ZigClangAPSInt_getRawData(int.?);
|
||||
const data = ZigClangAPSInt_getRawData(aps_int);
|
||||
var i: @TypeOf(num_limbs) = 0;
|
||||
while (i < num_limbs) : (i += 1) big.limbs[i] = data[i];
|
||||
const str = big.toString(c.a(), 10) catch |err| switch (err) {
|
||||
@ -2207,6 +2218,8 @@ fn transCreateNodeAPInt(c: *Context, int: ?*const ZigClangAPSInt) !*ast.Node {
|
||||
node.* = .{
|
||||
.token = token,
|
||||
};
|
||||
if (is_negative)
|
||||
ZigClangAPSInt_free(aps_int);
|
||||
return &node.base;
|
||||
}
|
||||
|
||||
@ -2803,7 +2816,7 @@ fn finishTransFnProto(
|
||||
const param = ZigClangFunctionDecl_getParamDecl(fn_decl.?, @intCast(c_uint, i));
|
||||
var param_name: []const u8 = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, param)));
|
||||
if (param_name.len < 1)
|
||||
param_name = "arg"[0..];
|
||||
param_name = try std.fmt.allocPrint(rp.c.a(), "arg_{}", .{rp.c.getMangle()});
|
||||
const checked_param_name = if (try scope.createAlias(rp.c, param_name)) |a| blk: {
|
||||
try fndef_scope.params.push(.{ .name = param_name, .alias = a });
|
||||
break :blk a;
|
||||
|
||||
@ -426,6 +426,180 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
},
|
||||
);
|
||||
|
||||
cases.addC_both("null statements",
|
||||
\\void foo(void) {
|
||||
\\ ;;;;;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo() void {
|
||||
\\ {}
|
||||
\\ {}
|
||||
\\ {}
|
||||
\\ {}
|
||||
\\ {}
|
||||
\\}
|
||||
});
|
||||
|
||||
if (builtin.os != builtin.Os.windows) {
|
||||
// Windows treats this as an enum with type c_int
|
||||
cases.add_both("big negative enum init values when C ABI supports long long enums",
|
||||
\\enum EnumWithInits {
|
||||
\\ VAL01 = 0,
|
||||
\\ VAL02 = 1,
|
||||
\\ VAL03 = 2,
|
||||
\\ VAL04 = 3,
|
||||
\\ VAL05 = -1,
|
||||
\\ VAL06 = -2,
|
||||
\\ VAL07 = -3,
|
||||
\\ VAL08 = -4,
|
||||
\\ VAL09 = VAL02 + VAL08,
|
||||
\\ VAL10 = -1000012000,
|
||||
\\ VAL11 = -1000161000,
|
||||
\\ VAL12 = -1000174001,
|
||||
\\ VAL13 = VAL09,
|
||||
\\ VAL14 = VAL10,
|
||||
\\ VAL15 = VAL11,
|
||||
\\ VAL16 = VAL13,
|
||||
\\ VAL17 = (VAL16 - VAL10 + 1),
|
||||
\\ VAL18 = 0x1000000000000000L,
|
||||
\\ VAL19 = VAL18 + VAL18 + VAL18 - 1,
|
||||
\\ VAL20 = VAL19 + VAL19,
|
||||
\\ VAL21 = VAL20 + 0xFFFFFFFFFFFFFFFF,
|
||||
\\ VAL22 = 0xFFFFFFFFFFFFFFFF + 1,
|
||||
\\ VAL23 = 0xFFFFFFFFFFFFFFFF,
|
||||
\\};
|
||||
, &[_][]const u8{
|
||||
\\pub const enum_EnumWithInits = extern enum(c_longlong) {
|
||||
\\ VAL01 = 0,
|
||||
\\ VAL02 = 1,
|
||||
\\ VAL03 = 2,
|
||||
\\ VAL04 = 3,
|
||||
\\ VAL05 = -1,
|
||||
\\ VAL06 = -2,
|
||||
\\ VAL07 = -3,
|
||||
\\ VAL08 = -4,
|
||||
\\ VAL09 = -3,
|
||||
\\ VAL10 = -1000012000,
|
||||
\\ VAL11 = -1000161000,
|
||||
\\ VAL12 = -1000174001,
|
||||
\\ VAL13 = -3,
|
||||
\\ VAL14 = -1000012000,
|
||||
\\ VAL15 = -1000161000,
|
||||
\\ VAL16 = -3,
|
||||
\\ VAL17 = 1000011998,
|
||||
\\ VAL18 = 1152921504606846976,
|
||||
\\ VAL19 = 3458764513820540927,
|
||||
\\ VAL20 = 6917529027641081854,
|
||||
\\ VAL21 = 6917529027641081853,
|
||||
\\ VAL22 = 0,
|
||||
\\ VAL23 = -1,
|
||||
\\};
|
||||
});
|
||||
}
|
||||
|
||||
cases.addC_both("predefined expressions",
|
||||
\\void foo(void) {
|
||||
\\ __func__;
|
||||
\\ __FUNCTION__;
|
||||
\\ __PRETTY_FUNCTION__;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo() void {
|
||||
\\ _ = "foo";
|
||||
\\ _ = "foo";
|
||||
\\ _ = "void foo(void)";
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC_both("ignore result, no function arguments",
|
||||
\\void foo() {
|
||||
\\ int a;
|
||||
\\ 1;
|
||||
\\ "hey";
|
||||
\\ 1 + 1;
|
||||
\\ 1 - 1;
|
||||
\\ a = 1;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo() void {
|
||||
\\ var a: c_int = undefined;
|
||||
\\ _ = 1;
|
||||
\\ _ = "hey";
|
||||
\\ _ = (1 + 1);
|
||||
\\ _ = (1 - 1);
|
||||
\\ a = 1;
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.add_2("qualified struct and enum",
|
||||
\\struct Foo {
|
||||
\\ int x;
|
||||
\\ int y;
|
||||
\\};
|
||||
\\enum Bar {
|
||||
\\ BarA,
|
||||
\\ BarB,
|
||||
\\};
|
||||
\\void func(struct Foo *a, enum Bar **b);
|
||||
, &[_][]const u8{
|
||||
\\pub const struct_Foo = extern struct {
|
||||
\\ x: c_int,
|
||||
\\ y: c_int,
|
||||
\\};
|
||||
\\pub const BarA = enum_Bar.A;
|
||||
\\pub const BarB = enum_Bar.B;
|
||||
\\pub const enum_Bar = extern enum {
|
||||
\\ A,
|
||||
\\ B,
|
||||
\\};
|
||||
\\pub extern fn func(a: [*c]struct_Foo, b: [*c][*c]enum_Bar) void;
|
||||
,
|
||||
\\pub const Foo = struct_Foo;
|
||||
\\pub const Bar = enum_Bar;
|
||||
});
|
||||
|
||||
cases.add_both("constant size array",
|
||||
\\void func(int array[20]);
|
||||
, &[_][]const u8{
|
||||
\\pub extern fn func(array: [*c]c_int) void;
|
||||
});
|
||||
|
||||
cases.add_both("__cdecl doesn't mess up function pointers",
|
||||
\\void foo(void (__cdecl *fn_ptr)(void));
|
||||
, &[_][]const u8{
|
||||
\\pub extern fn foo(fn_ptr: ?extern fn () void) void;
|
||||
});
|
||||
|
||||
cases.addC_both("void cast",
|
||||
\\void foo(int a) {
|
||||
\\ (void) a;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo(a: c_int) void {
|
||||
\\ _ = a;
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC_both("implicit cast to void *",
|
||||
\\void *foo(unsigned short *x) {
|
||||
\\ return x;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo(x: [*c]c_ushort) ?*c_void {
|
||||
\\ return @ptrCast(?*c_void, x);
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC_both("null pointer implicit cast",
|
||||
\\int* foo(void) {
|
||||
\\ return 0;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo() [*c]c_int {
|
||||
\\ return null;
|
||||
\\}
|
||||
});
|
||||
|
||||
/////////////// Cases that pass for only stage2 ////////////////
|
||||
|
||||
cases.add_2("Parameterless function prototypes",
|
||||
@ -904,145 +1078,75 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\};
|
||||
});
|
||||
|
||||
cases.add_2("undefined array global",
|
||||
\\int array[100] = {};
|
||||
, &[_][]const u8{
|
||||
\\pub export var array: [100]c_int = .{0} ** 100;
|
||||
});
|
||||
|
||||
cases.add_2("restrict -> noalias",
|
||||
\\void foo(void *restrict bar, void *restrict);
|
||||
, &[_][]const u8{
|
||||
\\pub extern fn foo(noalias bar: ?*c_void, noalias arg_1: ?*c_void) void;
|
||||
});
|
||||
|
||||
cases.add_2("assign",
|
||||
\\int max(int a) {
|
||||
\\ int tmp;
|
||||
\\ tmp = a;
|
||||
\\ a = tmp;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn max(a: c_int) c_int {
|
||||
\\ var tmp: c_int = undefined;
|
||||
\\ tmp = a;
|
||||
\\ a = tmp;
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.add_2("chaining assign",
|
||||
\\void max(int a) {
|
||||
\\ int b, c;
|
||||
\\ c = b = a;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn max(a: c_int) void {
|
||||
\\ var b: c_int = undefined;
|
||||
\\ var c: c_int = undefined;
|
||||
\\ c = blk: {
|
||||
\\ const _tmp_1 = a;
|
||||
\\ b = _tmp_1;
|
||||
\\ break :blk _tmp_1;
|
||||
\\ };
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.add_2("anonymous enum",
|
||||
\\enum {
|
||||
\\ One,
|
||||
\\ Two,
|
||||
\\};
|
||||
, &[_][]const u8{
|
||||
\\pub const One = enum_unnamed_1.One;
|
||||
\\pub const Two = enum_unnamed_1.Two;
|
||||
\\pub const enum_unnamed_1 = extern enum {
|
||||
\\ One,
|
||||
\\ Two,
|
||||
\\};
|
||||
});
|
||||
|
||||
cases.add_2("c style cast",
|
||||
\\int float_to_int(float a) {
|
||||
\\ return (int)a;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn float_to_int(a: f32) c_int {
|
||||
\\ return @floatToInt(c_int, a);
|
||||
\\}
|
||||
});
|
||||
|
||||
/////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
|
||||
|
||||
if (builtin.os != builtin.Os.windows) {
|
||||
// Windows treats this as an enum with type c_int
|
||||
cases.add("big negative enum init values when C ABI supports long long enums",
|
||||
\\enum EnumWithInits {
|
||||
\\ VAL01 = 0,
|
||||
\\ VAL02 = 1,
|
||||
\\ VAL03 = 2,
|
||||
\\ VAL04 = 3,
|
||||
\\ VAL05 = -1,
|
||||
\\ VAL06 = -2,
|
||||
\\ VAL07 = -3,
|
||||
\\ VAL08 = -4,
|
||||
\\ VAL09 = VAL02 + VAL08,
|
||||
\\ VAL10 = -1000012000,
|
||||
\\ VAL11 = -1000161000,
|
||||
\\ VAL12 = -1000174001,
|
||||
\\ VAL13 = VAL09,
|
||||
\\ VAL14 = VAL10,
|
||||
\\ VAL15 = VAL11,
|
||||
\\ VAL16 = VAL13,
|
||||
\\ VAL17 = (VAL16 - VAL10 + 1),
|
||||
\\ VAL18 = 0x1000000000000000L,
|
||||
\\ VAL19 = VAL18 + VAL18 + VAL18 - 1,
|
||||
\\ VAL20 = VAL19 + VAL19,
|
||||
\\ VAL21 = VAL20 + 0xFFFFFFFFFFFFFFFF,
|
||||
\\ VAL22 = 0xFFFFFFFFFFFFFFFF + 1,
|
||||
\\ VAL23 = 0xFFFFFFFFFFFFFFFF,
|
||||
\\};
|
||||
, &[_][]const u8{
|
||||
\\pub const enum_EnumWithInits = extern enum(c_longlong) {
|
||||
\\ VAL01 = 0,
|
||||
\\ VAL02 = 1,
|
||||
\\ VAL03 = 2,
|
||||
\\ VAL04 = 3,
|
||||
\\ VAL05 = -1,
|
||||
\\ VAL06 = -2,
|
||||
\\ VAL07 = -3,
|
||||
\\ VAL08 = -4,
|
||||
\\ VAL09 = -3,
|
||||
\\ VAL10 = -1000012000,
|
||||
\\ VAL11 = -1000161000,
|
||||
\\ VAL12 = -1000174001,
|
||||
\\ VAL13 = -3,
|
||||
\\ VAL14 = -1000012000,
|
||||
\\ VAL15 = -1000161000,
|
||||
\\ VAL16 = -3,
|
||||
\\ VAL17 = 1000011998,
|
||||
\\ VAL18 = 1152921504606846976,
|
||||
\\ VAL19 = 3458764513820540927,
|
||||
\\ VAL20 = 6917529027641081854,
|
||||
\\ VAL21 = 6917529027641081853,
|
||||
\\ VAL22 = 0,
|
||||
\\ VAL23 = -1,
|
||||
\\};
|
||||
});
|
||||
}
|
||||
|
||||
cases.add("predefined expressions",
|
||||
\\void foo(void) {
|
||||
\\ __func__;
|
||||
\\ __FUNCTION__;
|
||||
\\ __PRETTY_FUNCTION__;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub fn foo() void {
|
||||
\\ _ = "foo";
|
||||
\\ _ = "foo";
|
||||
\\ _ = "void foo(void)";
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.add("ignore result, no function arguments",
|
||||
\\void foo() {
|
||||
\\ int a;
|
||||
\\ 1;
|
||||
\\ "hey";
|
||||
\\ 1 + 1;
|
||||
\\ 1 - 1;
|
||||
\\ a = 1;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub fn foo() void {
|
||||
\\ var a: c_int = undefined;
|
||||
\\ _ = 1;
|
||||
\\ _ = "hey";
|
||||
\\ _ = (1 + 1);
|
||||
\\ _ = (1 - 1);
|
||||
\\ a = 1;
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.add("for loop with var init but empty body",
|
||||
\\void foo(void) {
|
||||
\\ for (int x = 0; x < 10; x++);
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub fn foo() void {
|
||||
\\ {
|
||||
\\ var x: c_int = 0;
|
||||
\\ while (x < 10) : (x += 1) {}
|
||||
\\ }
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.add("do while with empty body",
|
||||
\\void foo(void) {
|
||||
\\ do ; while (1);
|
||||
\\}
|
||||
, &[_][]const u8{ // TODO this should be if (1 != 0) break
|
||||
\\pub fn foo() void {
|
||||
\\ while (true) {
|
||||
\\ {}
|
||||
\\ if (!1) break;
|
||||
\\ }
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.add("for with empty body",
|
||||
\\void foo(void) {
|
||||
\\ for (;;);
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub fn foo() void {
|
||||
\\ while (true) {}
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.add("while with empty body",
|
||||
\\void foo(void) {
|
||||
\\ while (1);
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub fn foo() void {
|
||||
\\ while (1 != 0) {}
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addAllowWarnings("simple data types",
|
||||
\\#include <stdint.h>
|
||||
\\int foo(char a, unsigned char b, signed char c);
|
||||
@ -1067,56 +1171,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.add("restrict -> noalias",
|
||||
\\void foo(void *restrict bar, void *restrict);
|
||||
, &[_][]const u8{
|
||||
\\pub extern fn foo(noalias bar: ?*c_void, noalias arg1: ?*c_void) void;
|
||||
});
|
||||
|
||||
cases.add("qualified struct and enum",
|
||||
\\struct Foo {
|
||||
\\ int x;
|
||||
\\ int y;
|
||||
\\};
|
||||
\\enum Bar {
|
||||
\\ BarA,
|
||||
\\ BarB,
|
||||
\\};
|
||||
\\void func(struct Foo *a, enum Bar **b);
|
||||
, &[_][]const u8{
|
||||
\\pub const struct_Foo = extern struct {
|
||||
\\ x: c_int,
|
||||
\\ y: c_int,
|
||||
\\};
|
||||
,
|
||||
\\pub const enum_Bar = extern enum {
|
||||
\\ A,
|
||||
\\ B,
|
||||
\\};
|
||||
,
|
||||
\\pub const BarA = enum_Bar.A;
|
||||
,
|
||||
\\pub const BarB = enum_Bar.B;
|
||||
,
|
||||
\\pub extern fn func(a: [*c]struct_Foo, b: [*c]([*c]enum_Bar)) void;
|
||||
,
|
||||
\\pub const Foo = struct_Foo;
|
||||
,
|
||||
\\pub const Bar = enum_Bar;
|
||||
});
|
||||
|
||||
cases.add("constant size array",
|
||||
\\void func(int array[20]);
|
||||
, &[_][]const u8{
|
||||
\\pub extern fn func(array: [*c]c_int) void;
|
||||
});
|
||||
|
||||
cases.add("__cdecl doesn't mess up function pointers",
|
||||
\\void foo(void (__cdecl *fn_ptr)(void));
|
||||
, &[_][]const u8{
|
||||
\\pub extern fn foo(fn_ptr: ?extern fn () void) void;
|
||||
});
|
||||
|
||||
cases.add("macro defines string literal with hex",
|
||||
\\#define FOO "aoeu\xab derp"
|
||||
\\#define FOO2 "aoeu\x0007a derp"
|
||||
@ -1266,38 +1320,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC("assign",
|
||||
\\int max(int a) {
|
||||
\\ int tmp;
|
||||
\\ tmp = a;
|
||||
\\ a = tmp;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn max(_arg_a: c_int) c_int {
|
||||
\\ var a = _arg_a;
|
||||
\\ var tmp: c_int = undefined;
|
||||
\\ tmp = a;
|
||||
\\ a = tmp;
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC("chaining assign",
|
||||
\\void max(int a) {
|
||||
\\ int b, c;
|
||||
\\ c = b = a;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn max(a: c_int) void {
|
||||
\\ var b: c_int = undefined;
|
||||
\\ var c: c_int = undefined;
|
||||
\\ c = (x: {
|
||||
\\ const _tmp = a;
|
||||
\\ b = _tmp;
|
||||
\\ break :x _tmp;
|
||||
\\ });
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC("shift right assign with a fixed size type",
|
||||
\\#include <stdint.h>
|
||||
\\int log2(uint32_t a) {
|
||||
@ -1318,16 +1340,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.add("anonymous enum",
|
||||
\\enum {
|
||||
\\ One,
|
||||
\\ Two,
|
||||
\\};
|
||||
, &[_][]const u8{
|
||||
\\pub const One = 0;
|
||||
\\pub const Two = 1;
|
||||
});
|
||||
|
||||
cases.addC("function call",
|
||||
\\static void bar(void) { }
|
||||
\\static int baz(void) { return 0; }
|
||||
@ -1362,26 +1374,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC("null statements",
|
||||
\\void foo(void) {
|
||||
\\ ;;;;;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo() void {
|
||||
\\ {}
|
||||
\\ {}
|
||||
\\ {}
|
||||
\\ {}
|
||||
\\ {}
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.add("undefined array global",
|
||||
\\int array[100];
|
||||
, &[_][]const u8{
|
||||
\\pub var array: [100]c_int = undefined;
|
||||
});
|
||||
|
||||
cases.addC("array access",
|
||||
\\int array[100];
|
||||
\\int foo(int index) {
|
||||
@ -1394,36 +1386,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC("c style cast",
|
||||
\\int float_to_int(float a) {
|
||||
\\ return (int)a;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn float_to_int(a: f32) c_int {
|
||||
\\ return @as(c_int, a);
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC("void cast",
|
||||
\\void foo(int a) {
|
||||
\\ (void) a;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo(a: c_int) void {
|
||||
\\ _ = a;
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC("implicit cast to void *",
|
||||
\\void *foo(unsigned short *x) {
|
||||
\\ return x;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo(x: [*c]c_ushort) ?*c_void {
|
||||
\\ return @ptrCast(?*c_void, x);
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC("sizeof",
|
||||
\\#include <stddef.h>
|
||||
\\size_t size_of(void) {
|
||||
@ -1435,29 +1397,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC("null pointer implicit cast",
|
||||
\\int* foo(void) {
|
||||
\\ return 0;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo() [*c]c_int {
|
||||
\\ return null;
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC("comma operator",
|
||||
\\int foo(void) {
|
||||
\\ return 1, 2;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo() c_int {
|
||||
\\ return x: {
|
||||
\\ _ = 1;
|
||||
\\ break :x 2;
|
||||
\\ };
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC("statement expression",
|
||||
\\int foo(void) {
|
||||
\\ return ({
|
||||
@ -2292,4 +2231,159 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ }
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.add("for loop with var init but empty body",
|
||||
\\void foo(void) {
|
||||
\\ for (int x = 0; x < 10; x++);
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub fn foo() void {
|
||||
\\ {
|
||||
\\ var x: c_int = 0;
|
||||
\\ while (x < 10) : (x += 1) {}
|
||||
\\ }
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.add("do while with empty body",
|
||||
\\void foo(void) {
|
||||
\\ do ; while (1);
|
||||
\\}
|
||||
, &[_][]const u8{ // TODO this should be if (1 != 0) break
|
||||
\\pub fn foo() void {
|
||||
\\ while (true) {
|
||||
\\ {}
|
||||
\\ if (!1) break;
|
||||
\\ }
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.add("for with empty body",
|
||||
\\void foo(void) {
|
||||
\\ for (;;);
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub fn foo() void {
|
||||
\\ while (true) {}
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.add("while with empty body",
|
||||
\\void foo(void) {
|
||||
\\ while (1);
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub fn foo() void {
|
||||
\\ while (1 != 0) {}
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.add("undefined array global",
|
||||
\\int array[100];
|
||||
, &[_][]const u8{
|
||||
\\pub var array: [100]c_int = undefined;
|
||||
});
|
||||
|
||||
cases.add("qualified struct and enum",
|
||||
\\struct Foo {
|
||||
\\ int x;
|
||||
\\ int y;
|
||||
\\};
|
||||
\\enum Bar {
|
||||
\\ BarA,
|
||||
\\ BarB,
|
||||
\\};
|
||||
\\void func(struct Foo *a, enum Bar **b);
|
||||
, &[_][]const u8{
|
||||
\\pub const struct_Foo = extern struct {
|
||||
\\ x: c_int,
|
||||
\\ y: c_int,
|
||||
\\};
|
||||
,
|
||||
\\pub const enum_Bar = extern enum {
|
||||
\\ A,
|
||||
\\ B,
|
||||
\\};
|
||||
,
|
||||
\\pub const BarA = enum_Bar.A;
|
||||
,
|
||||
\\pub const BarB = enum_Bar.B;
|
||||
,
|
||||
\\pub extern fn func(a: [*c]struct_Foo, b: [*c]([*c]enum_Bar)) void;
|
||||
,
|
||||
\\pub const Foo = struct_Foo;
|
||||
,
|
||||
\\pub const Bar = enum_Bar;
|
||||
});
|
||||
|
||||
cases.add("restrict -> noalias",
|
||||
\\void foo(void *restrict bar, void *restrict);
|
||||
, &[_][]const u8{
|
||||
\\pub extern fn foo(noalias bar: ?*c_void, noalias arg1: ?*c_void) void;
|
||||
});
|
||||
|
||||
cases.addC("assign",
|
||||
\\int max(int a) {
|
||||
\\ int tmp;
|
||||
\\ tmp = a;
|
||||
\\ a = tmp;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn max(_arg_a: c_int) c_int {
|
||||
\\ var a = _arg_a;
|
||||
\\ var tmp: c_int = undefined;
|
||||
\\ tmp = a;
|
||||
\\ a = tmp;
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC("chaining assign",
|
||||
\\void max(int a) {
|
||||
\\ int b, c;
|
||||
\\ c = b = a;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn max(a: c_int) void {
|
||||
\\ var b: c_int = undefined;
|
||||
\\ var c: c_int = undefined;
|
||||
\\ c = (x: {
|
||||
\\ const _tmp = a;
|
||||
\\ b = _tmp;
|
||||
\\ break :x _tmp;
|
||||
\\ });
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.add("anonymous enum",
|
||||
\\enum {
|
||||
\\ One,
|
||||
\\ Two,
|
||||
\\};
|
||||
, &[_][]const u8{
|
||||
\\pub const One = 0;
|
||||
\\pub const Two = 1;
|
||||
});
|
||||
|
||||
cases.addC("c style cast",
|
||||
\\int float_to_int(float a) {
|
||||
\\ return (int)a;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn float_to_int(a: f32) c_int {
|
||||
\\ return @as(c_int, a);
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC("comma operator",
|
||||
\\int foo(void) {
|
||||
\\ return 1, 2;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo() c_int {
|
||||
\\ return x: {
|
||||
\\ _ = 1;
|
||||
\\ break :x 2;
|
||||
\\ };
|
||||
\\}
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user