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 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 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 ZigClangQualType_getCanonicalType(self: struct_ZigClangQualType) struct_ZigClangQualType;
|
||||
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));
|
||||
},
|
||||
.Typedef => {
|
||||
try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for typedefs", .{});
|
||||
try resolveTypeDef(c, @ptrCast(*const ZigClangTypedefNameDecl, decl));
|
||||
},
|
||||
.Enum => {
|
||||
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);
|
||||
}
|
||||
|
||||
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 {
|
||||
used,
|
||||
unused,
|
||||
@ -1534,6 +1576,13 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
|
||||
node.rhs = try transQualType(rp, child_qt, source_loc);
|
||||
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 => {
|
||||
const type_name = rp.c.str(ZigClangType_getTypeClassName(ty));
|
||||
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 {
|
||||
fn_name: []const u8,
|
||||
has_body: bool,
|
||||
@ -1691,7 +1749,8 @@ fn finishTransFnProto(
|
||||
break :blk try appendIdentifier(rp.c, "noreturn");
|
||||
} else {
|
||||
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");
|
||||
} else {
|
||||
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,
|
||||
.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 {
|
||||
|
@ -84,6 +84,82 @@ pub fn addCases(cases: *tests.TranslateCContext) 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.add_2("Parameterless function prototypes",
|
||||
@ -144,20 +220,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\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) {
|
||||
// Windows treats this as an enum with type c_int
|
||||
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;
|
||||
});
|
||||
|
||||
cases.add_both("noreturn attribute",
|
||||
\\void foo(void) __attribute__((noreturn));
|
||||
, &[_][]const u8{
|
||||
\\pub extern fn foo() noreturn;
|
||||
});
|
||||
|
||||
cases.add("simple function",
|
||||
\\int abs(int 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",
|
||||
\\extern void (*fn_ptr)(void);
|
||||
\\#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",
|
||||
\\int max(int a, int 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",
|
||||
\\void foo(void) {
|
||||
\\ int i = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user