translate-c-2 typedef
This commit is contained in:
parent
eb057ef41c
commit
41a67126a5
@ -735,7 +735,7 @@ pub extern fn ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl: ?*const s
|
|||||||
pub extern fn ZigClangEnumDecl_getIntegerType(self: ?*const struct_ZigClangEnumDecl) struct_ZigClangQualType;
|
pub extern fn ZigClangEnumDecl_getIntegerType(self: ?*const struct_ZigClangEnumDecl) struct_ZigClangQualType;
|
||||||
pub extern fn ZigClangDecl_getName_bytes_begin(decl: ?*const struct_ZigClangDecl) [*c]const u8;
|
pub extern fn ZigClangDecl_getName_bytes_begin(decl: ?*const struct_ZigClangDecl) [*c]const u8;
|
||||||
pub extern fn ZigClangSourceLocation_eq(a: struct_ZigClangSourceLocation, b: struct_ZigClangSourceLocation) bool;
|
pub extern fn ZigClangSourceLocation_eq(a: struct_ZigClangSourceLocation, b: struct_ZigClangSourceLocation) bool;
|
||||||
pub extern fn ZigClangTypedefType_getDecl(self: ?*const struct_ZigClangTypedefType) ?*const struct_ZigClangTypedefNameDecl;
|
pub extern fn ZigClangTypedefType_getDecl(self: ?*const struct_ZigClangTypedefType) *const struct_ZigClangTypedefNameDecl;
|
||||||
pub extern fn ZigClangTypedefNameDecl_getUnderlyingType(self: ?*const struct_ZigClangTypedefNameDecl) struct_ZigClangQualType;
|
pub extern fn ZigClangTypedefNameDecl_getUnderlyingType(self: ?*const struct_ZigClangTypedefNameDecl) struct_ZigClangQualType;
|
||||||
pub extern fn ZigClangQualType_getCanonicalType(self: struct_ZigClangQualType) struct_ZigClangQualType;
|
pub extern fn ZigClangQualType_getCanonicalType(self: struct_ZigClangQualType) struct_ZigClangQualType;
|
||||||
pub extern fn ZigClangQualType_getTypeClass(self: struct_ZigClangQualType) ZigClangTypeClass;
|
pub extern fn ZigClangQualType_getTypeClass(self: struct_ZigClangQualType) ZigClangTypeClass;
|
||||||
|
@ -220,7 +220,7 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void {
|
|||||||
return visitFnDecl(c, @ptrCast(*const ZigClangFunctionDecl, decl));
|
return visitFnDecl(c, @ptrCast(*const ZigClangFunctionDecl, decl));
|
||||||
},
|
},
|
||||||
.Typedef => {
|
.Typedef => {
|
||||||
try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for typedefs", .{});
|
try resolveTypeDef(c, @ptrCast(*const ZigClangTypedefNameDecl, decl));
|
||||||
},
|
},
|
||||||
.Enum => {
|
.Enum => {
|
||||||
try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for enums", .{});
|
try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for enums", .{});
|
||||||
@ -384,6 +384,48 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
|
|||||||
return addTopLevelDecl(c, var_name, &node.base);
|
return addTopLevelDecl(c, var_name, &node.base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Error!void {
|
||||||
|
if (try c.decl_table.put(@ptrToInt(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl)), {})) |_| return; // Avoid processing this decl twice
|
||||||
|
const rp = makeRestorePoint(c);
|
||||||
|
const visib_tok = try appendToken(c, .Keyword_pub, "pub");
|
||||||
|
const const_tok = try appendToken(c, .Keyword_const, "const");
|
||||||
|
|
||||||
|
const typedef_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, typedef_decl)));
|
||||||
|
const name_tok = try appendToken(c, .Identifier, typedef_name);
|
||||||
|
const eq_tok = try appendToken(c, .Equal, "=");
|
||||||
|
|
||||||
|
const child_qt = ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl);
|
||||||
|
const typedef_loc = ZigClangTypedefNameDecl_getLocation(typedef_decl);
|
||||||
|
const type_node = transQualType(rp, child_qt, typedef_loc) catch |err| switch (err) {
|
||||||
|
error.UnsupportedType => {
|
||||||
|
const node = try failDecl(c, typedef_loc, typedef_name, "unable to resolve typedef child type", .{});
|
||||||
|
_ = try c.decl_table.put(@ptrToInt(typedef_decl), node);
|
||||||
|
return node;
|
||||||
|
},
|
||||||
|
error.OutOfMemory => |e| return e,
|
||||||
|
};
|
||||||
|
|
||||||
|
const node = try c.a().create(ast.Node.VarDecl);
|
||||||
|
node.* = ast.Node.VarDecl{
|
||||||
|
.base = ast.Node{ .id = .VarDecl },
|
||||||
|
.doc_comments = null,
|
||||||
|
.visib_token = visib_tok,
|
||||||
|
.thread_local_token = null,
|
||||||
|
.name_token = name_tok,
|
||||||
|
.eq_token = eq_tok,
|
||||||
|
.mut_token = const_tok,
|
||||||
|
.comptime_token = null,
|
||||||
|
.extern_export_token = null,
|
||||||
|
.lib_name = null,
|
||||||
|
.type_node = null,
|
||||||
|
.align_node = null,
|
||||||
|
.section_node = null,
|
||||||
|
.init_node = type_node,
|
||||||
|
.semicolon_token = try appendToken(c, .Semicolon, ";"),
|
||||||
|
};
|
||||||
|
try addTopLevelDecl(c, typedef_name, &node.base);
|
||||||
|
}
|
||||||
|
|
||||||
const ResultUsed = enum {
|
const ResultUsed = enum {
|
||||||
used,
|
used,
|
||||||
unused,
|
unused,
|
||||||
@ -1534,6 +1576,13 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
|
|||||||
node.rhs = try transQualType(rp, child_qt, source_loc);
|
node.rhs = try transQualType(rp, child_qt, source_loc);
|
||||||
return &node.base;
|
return &node.base;
|
||||||
},
|
},
|
||||||
|
.Typedef => {
|
||||||
|
const typedef_ty = @ptrCast(*const ZigClangTypedefType, ty);
|
||||||
|
|
||||||
|
const typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
|
||||||
|
const typedef_name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, typedef_decl)));
|
||||||
|
return appendIdentifier(rp.c, typedef_name);
|
||||||
|
},
|
||||||
else => {
|
else => {
|
||||||
const type_name = rp.c.str(ZigClangType_getTypeClassName(ty));
|
const type_name = rp.c.str(ZigClangType_getTypeClassName(ty));
|
||||||
return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported type: '{}'", .{type_name});
|
return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported type: '{}'", .{type_name});
|
||||||
@ -1541,6 +1590,15 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn isCVoid(qt: ZigClangQualType) bool {
|
||||||
|
const ty = ZigClangQualType_getTypePtr(qt);
|
||||||
|
if (ZigClangType_getTypeClass(ty) == .Builtin) {
|
||||||
|
const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty);
|
||||||
|
return ZigClangBuiltinType_getKind(builtin_ty) == .Void;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const FnDeclContext = struct {
|
const FnDeclContext = struct {
|
||||||
fn_name: []const u8,
|
fn_name: []const u8,
|
||||||
has_body: bool,
|
has_body: bool,
|
||||||
@ -1691,7 +1749,8 @@ fn finishTransFnProto(
|
|||||||
break :blk try appendIdentifier(rp.c, "noreturn");
|
break :blk try appendIdentifier(rp.c, "noreturn");
|
||||||
} else {
|
} else {
|
||||||
const return_qt = ZigClangFunctionType_getReturnType(fn_ty);
|
const return_qt = ZigClangFunctionType_getReturnType(fn_ty);
|
||||||
if (ZigClangType_isVoidType(qualTypeCanon(return_qt))) {
|
if (isCVoid(return_qt)) {
|
||||||
|
// convert primitive c_void to actual void (only for return type)
|
||||||
break :blk try appendIdentifier(rp.c, "void");
|
break :blk try appendIdentifier(rp.c, "void");
|
||||||
} else {
|
} else {
|
||||||
break :blk transQualType(rp, return_qt, source_loc) catch |err| switch (err) {
|
break :blk transQualType(rp, return_qt, source_loc) catch |err| switch (err) {
|
||||||
@ -1786,7 +1845,7 @@ fn failDecl(c: *Context, loc: ZigClangSourceLocation, name: []const u8, comptime
|
|||||||
.init_node = &call_node.base,
|
.init_node = &call_node.base,
|
||||||
.semicolon_token = semi_tok,
|
.semicolon_token = semi_tok,
|
||||||
};
|
};
|
||||||
try c.tree.root_node.decls.push(&var_decl_node.base);
|
try addTopLevelDecl(c, name, &var_decl_node.base);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn appendToken(c: *Context, token_id: Token.Id, bytes: []const u8) !ast.TokenIndex {
|
fn appendToken(c: *Context, token_id: Token.Id, bytes: []const u8) !ast.TokenIndex {
|
||||||
|
@ -84,6 +84,82 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||||||
\\pub fn bar() void {}
|
\\pub fn bar() void {}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
cases.add_both("typedef void",
|
||||||
|
\\typedef void Foo;
|
||||||
|
\\Foo fun(Foo *a);
|
||||||
|
, &[_][]const u8{
|
||||||
|
\\pub const Foo = c_void;
|
||||||
|
,
|
||||||
|
\\pub extern fn fun(a: ?*Foo) Foo;
|
||||||
|
});
|
||||||
|
|
||||||
|
cases.add_both("duplicate typedef",
|
||||||
|
\\typedef long foo;
|
||||||
|
\\typedef int bar;
|
||||||
|
\\typedef long foo;
|
||||||
|
\\typedef int baz;
|
||||||
|
, &[_][]const u8{
|
||||||
|
\\pub const foo = c_long;
|
||||||
|
\\pub const bar = c_int;
|
||||||
|
\\pub const baz = c_int;
|
||||||
|
});
|
||||||
|
|
||||||
|
cases.add_both("casting pointers to ints and ints to pointers",
|
||||||
|
\\void foo(void);
|
||||||
|
\\void bar(void) {
|
||||||
|
\\ void *func_ptr = foo;
|
||||||
|
\\ void (*typed_func_ptr)(void) = (void (*)(void)) (unsigned long) func_ptr;
|
||||||
|
\\}
|
||||||
|
, &[_][]const u8{
|
||||||
|
\\pub extern fn foo() void;
|
||||||
|
\\pub export fn bar() void {
|
||||||
|
\\ var func_ptr: ?*c_void = @ptrCast(?*c_void, foo);
|
||||||
|
\\ var typed_func_ptr: ?extern fn () void = @intToPtr(?extern fn () void, @as(c_ulong, @ptrToInt(func_ptr)));
|
||||||
|
\\}
|
||||||
|
});
|
||||||
|
|
||||||
|
cases.add_both("noreturn attribute",
|
||||||
|
\\void foo(void) __attribute__((noreturn));
|
||||||
|
, &[_][]const u8{
|
||||||
|
\\pub extern fn foo() noreturn;
|
||||||
|
});
|
||||||
|
|
||||||
|
cases.add_both("add, sub, mul, div, rem",
|
||||||
|
\\int s(int a, int b) {
|
||||||
|
\\ int c;
|
||||||
|
\\ c = a + b;
|
||||||
|
\\ c = a - b;
|
||||||
|
\\ c = a * b;
|
||||||
|
\\ c = a / b;
|
||||||
|
\\ c = a % b;
|
||||||
|
\\}
|
||||||
|
\\unsigned u(unsigned a, unsigned b) {
|
||||||
|
\\ unsigned c;
|
||||||
|
\\ c = a + b;
|
||||||
|
\\ c = a - b;
|
||||||
|
\\ c = a * b;
|
||||||
|
\\ c = a / b;
|
||||||
|
\\ c = a % b;
|
||||||
|
\\}
|
||||||
|
, &[_][]const u8{
|
||||||
|
\\pub export fn s(a: c_int, b: c_int) c_int {
|
||||||
|
\\ var c: c_int = undefined;
|
||||||
|
\\ c = (a + b);
|
||||||
|
\\ c = (a - b);
|
||||||
|
\\ c = (a * b);
|
||||||
|
\\ c = @divTrunc(a, b);
|
||||||
|
\\ c = @rem(a, b);
|
||||||
|
\\}
|
||||||
|
\\pub export fn u(a: c_uint, b: c_uint) c_uint {
|
||||||
|
\\ var c: c_uint = undefined;
|
||||||
|
\\ c = (a +% b);
|
||||||
|
\\ c = (a -% b);
|
||||||
|
\\ c = (a *% b);
|
||||||
|
\\ c = (a / b);
|
||||||
|
\\ c = (a % b);
|
||||||
|
\\}
|
||||||
|
});
|
||||||
|
|
||||||
/////////////// Cases that pass for only stage2 ////////////////
|
/////////////// Cases that pass for only stage2 ////////////////
|
||||||
|
|
||||||
cases.add_2("Parameterless function prototypes",
|
cases.add_2("Parameterless function prototypes",
|
||||||
@ -144,20 +220,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||||||
\\pub const REDISMODULE_READ = 1 << 0;
|
\\pub const REDISMODULE_READ = 1 << 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
cases.add_both("casting pointers to ints and ints to pointers",
|
|
||||||
\\void foo(void);
|
|
||||||
\\void bar(void) {
|
|
||||||
\\ void *func_ptr = foo;
|
|
||||||
\\ void (*typed_func_ptr)(void) = (void (*)(void)) (unsigned long) func_ptr;
|
|
||||||
\\}
|
|
||||||
, &[_][]const u8{
|
|
||||||
\\pub extern fn foo() void;
|
|
||||||
\\pub export fn bar() void {
|
|
||||||
\\ var func_ptr: ?*c_void = @ptrCast(?*c_void, foo);
|
|
||||||
\\ var typed_func_ptr: ?extern fn () void = @intToPtr(?extern fn () void, @as(c_ulong, @ptrToInt(func_ptr)));
|
|
||||||
\\}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (builtin.os != builtin.Os.windows) {
|
if (builtin.os != builtin.Os.windows) {
|
||||||
// Windows treats this as an enum with type c_int
|
// Windows treats this as an enum with type c_int
|
||||||
cases.add("big negative enum init values when C ABI supports long long enums",
|
cases.add("big negative enum init values when C ABI supports long long enums",
|
||||||
@ -330,12 +392,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||||||
\\pub extern fn baz(a: i8, b: i16, c: i32, d: i64) void;
|
\\pub extern fn baz(a: i8, b: i16, c: i32, d: i64) void;
|
||||||
});
|
});
|
||||||
|
|
||||||
cases.add_both("noreturn attribute",
|
|
||||||
\\void foo(void) __attribute__((noreturn));
|
|
||||||
, &[_][]const u8{
|
|
||||||
\\pub extern fn foo() noreturn;
|
|
||||||
});
|
|
||||||
|
|
||||||
cases.add("simple function",
|
cases.add("simple function",
|
||||||
\\int abs(int a) {
|
\\int abs(int a) {
|
||||||
\\ return a < 0 ? -a : a;
|
\\ return a < 0 ? -a : a;
|
||||||
@ -512,15 +568,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||||||
\\};
|
\\};
|
||||||
});
|
});
|
||||||
|
|
||||||
cases.add("typedef void",
|
|
||||||
\\typedef void Foo;
|
|
||||||
\\Foo fun(Foo *a);
|
|
||||||
, &[_][]const u8{
|
|
||||||
\\pub const Foo = c_void;
|
|
||||||
,
|
|
||||||
\\pub extern fn fun(a: ?*Foo) Foo;
|
|
||||||
});
|
|
||||||
|
|
||||||
cases.add("generate inline func for #define global extern fn",
|
cases.add("generate inline func for #define global extern fn",
|
||||||
\\extern void (*fn_ptr)(void);
|
\\extern void (*fn_ptr)(void);
|
||||||
\\#define foo fn_ptr
|
\\#define foo fn_ptr
|
||||||
@ -720,42 +767,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||||||
\\}
|
\\}
|
||||||
});
|
});
|
||||||
|
|
||||||
cases.add_both("add, sub, mul, div, rem",
|
|
||||||
\\int s(int a, int b) {
|
|
||||||
\\ int c;
|
|
||||||
\\ c = a + b;
|
|
||||||
\\ c = a - b;
|
|
||||||
\\ c = a * b;
|
|
||||||
\\ c = a / b;
|
|
||||||
\\ c = a % b;
|
|
||||||
\\}
|
|
||||||
\\unsigned u(unsigned a, unsigned b) {
|
|
||||||
\\ unsigned c;
|
|
||||||
\\ c = a + b;
|
|
||||||
\\ c = a - b;
|
|
||||||
\\ c = a * b;
|
|
||||||
\\ c = a / b;
|
|
||||||
\\ c = a % b;
|
|
||||||
\\}
|
|
||||||
, &[_][]const u8{
|
|
||||||
\\pub export fn s(a: c_int, b: c_int) c_int {
|
|
||||||
\\ var c: c_int = undefined;
|
|
||||||
\\ c = (a + b);
|
|
||||||
\\ c = (a - b);
|
|
||||||
\\ c = (a * b);
|
|
||||||
\\ c = @divTrunc(a, b);
|
|
||||||
\\ c = @rem(a, b);
|
|
||||||
\\}
|
|
||||||
\\pub export fn u(a: c_uint, b: c_uint) c_uint {
|
|
||||||
\\ var c: c_uint = undefined;
|
|
||||||
\\ c = (a +% b);
|
|
||||||
\\ c = (a -% b);
|
|
||||||
\\ c = (a *% b);
|
|
||||||
\\ c = (a / b);
|
|
||||||
\\ c = (a % b);
|
|
||||||
\\}
|
|
||||||
});
|
|
||||||
|
|
||||||
cases.add("bitwise binary operators",
|
cases.add("bitwise binary operators",
|
||||||
\\int max(int a, int b) {
|
\\int max(int a, int b) {
|
||||||
\\ return (a & b) ^ (a | b);
|
\\ return (a & b) ^ (a | b);
|
||||||
@ -1148,17 +1159,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||||||
\\}
|
\\}
|
||||||
});
|
});
|
||||||
|
|
||||||
cases.add("duplicate typedef",
|
|
||||||
\\typedef long foo;
|
|
||||||
\\typedef int bar;
|
|
||||||
\\typedef long foo;
|
|
||||||
\\typedef int baz;
|
|
||||||
, &[_][]const u8{
|
|
||||||
\\pub const foo = c_long;
|
|
||||||
\\pub const bar = c_int;
|
|
||||||
\\pub const baz = c_int;
|
|
||||||
});
|
|
||||||
|
|
||||||
cases.add("post increment/decrement",
|
cases.add("post increment/decrement",
|
||||||
\\void foo(void) {
|
\\void foo(void) {
|
||||||
\\ int i = 0;
|
\\ int i = 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user