translate-c-2 implement enums
This commit is contained in:
parent
1a967db083
commit
e57e3602e7
|
@ -193,6 +193,7 @@ fn renderRoot(
|
|||
fn renderExtraNewline(tree: *ast.Tree, stream: var, start_col: *usize, node: *ast.Node) @TypeOf(stream).Child.Error!void {
|
||||
const first_token = node.firstToken();
|
||||
var prev_token = first_token;
|
||||
if (prev_token == 0) return;
|
||||
while (tree.tokens.at(prev_token - 1).id == .DocComment) {
|
||||
prev_token -= 1;
|
||||
}
|
||||
|
|
|
@ -713,6 +713,10 @@ pub const ZigClangRecordDecl_field_iterator = extern struct {
|
|||
opaque: *c_void,
|
||||
};
|
||||
|
||||
pub const ZigClangEnumDecl_enumerator_iterator = extern struct {
|
||||
opaque: *c_void,
|
||||
};
|
||||
|
||||
pub extern fn ZigClangSourceManager_getSpellingLoc(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) struct_ZigClangSourceLocation;
|
||||
pub extern fn ZigClangSourceManager_getFilename(self: *const struct_ZigClangSourceManager, SpellingLoc: struct_ZigClangSourceLocation) ?[*:0]const u8;
|
||||
pub extern fn ZigClangSourceManager_getSpellingLineNumber(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint;
|
||||
|
@ -723,7 +727,7 @@ pub extern fn ZigClangASTUnit_getASTContext(self: ?*struct_ZigClangASTUnit) ?*st
|
|||
pub extern fn ZigClangASTUnit_getSourceManager(self: *struct_ZigClangASTUnit) *struct_ZigClangSourceManager;
|
||||
pub extern fn ZigClangASTUnit_visitLocalTopLevelDecls(self: *struct_ZigClangASTUnit, context: ?*c_void, Fn: ?extern fn (?*c_void, *const struct_ZigClangDecl) bool) bool;
|
||||
pub extern fn ZigClangRecordType_getDecl(record_ty: ?*const struct_ZigClangRecordType) *const struct_ZigClangRecordDecl;
|
||||
pub extern fn ZigClangEnumType_getDecl(record_ty: ?*const struct_ZigClangEnumType) ?*const struct_ZigClangEnumDecl;
|
||||
pub extern fn ZigClangEnumType_getDecl(record_ty: ?*const struct_ZigClangEnumType) *const struct_ZigClangEnumDecl;
|
||||
pub extern fn ZigClangRecordDecl_getCanonicalDecl(record_decl: ?*const struct_ZigClangRecordDecl) ?*const struct_ZigClangTagDecl;
|
||||
pub extern fn ZigClangEnumDecl_getCanonicalDecl(self: ?*const struct_ZigClangEnumDecl) ?*const struct_ZigClangTagDecl;
|
||||
pub extern fn ZigClangTypedefNameDecl_getCanonicalDecl(self: ?*const struct_ZigClangTypedefNameDecl) ?*const struct_ZigClangTypedefNameDecl;
|
||||
|
@ -742,6 +746,11 @@ pub extern fn ZigClangRecordDecl_field_iterator_next(ZigClangRecordDecl_field_it
|
|||
pub extern fn ZigClangRecordDecl_field_iterator_deref(ZigClangRecordDecl_field_iterator) *const struct_ZigClangFieldDecl;
|
||||
pub extern fn ZigClangRecordDecl_field_iterator_neq(ZigClangRecordDecl_field_iterator, ZigClangRecordDecl_field_iterator) bool;
|
||||
pub extern fn ZigClangEnumDecl_getIntegerType(self: ?*const struct_ZigClangEnumDecl) struct_ZigClangQualType;
|
||||
pub extern fn ZigClangEnumDecl_enumerator_begin(*const ZigClangEnumDecl) ZigClangEnumDecl_enumerator_iterator;
|
||||
pub extern fn ZigClangEnumDecl_enumerator_end(*const ZigClangEnumDecl) ZigClangEnumDecl_enumerator_iterator;
|
||||
pub extern fn ZigClangEnumDecl_enumerator_iterator_next(ZigClangEnumDecl_enumerator_iterator) ZigClangEnumDecl_enumerator_iterator;
|
||||
pub extern fn ZigClangEnumDecl_enumerator_iterator_deref(ZigClangEnumDecl_enumerator_iterator) *const ZigClangEnumConstantDecl;
|
||||
pub extern fn ZigClangEnumDecl_enumerator_iterator_neq(ZigClangEnumDecl_enumerator_iterator, ZigClangEnumDecl_enumerator_iterator) bool;
|
||||
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;
|
||||
|
@ -992,6 +1001,8 @@ pub extern fn ZigClangBinaryOperator_getLHS(*const ZigClangBinaryOperator) *cons
|
|||
pub extern fn ZigClangBinaryOperator_getRHS(*const ZigClangBinaryOperator) *const ZigClangExpr;
|
||||
pub extern fn ZigClangBinaryOperator_getType(*const ZigClangBinaryOperator) ZigClangQualType;
|
||||
|
||||
pub extern fn ZigClangDecayedType_getDecayedType(*const ZigClangDecayedType) ZigClangQualType;
|
||||
|
||||
pub extern fn ZigClangStringLiteral_getKind(*const ZigClangStringLiteral) ZigClangStringLiteral_StringKind;
|
||||
pub extern fn ZigClangStringLiteral_getString_bytes_begin_size(*const ZigClangStringLiteral, *usize) [*c]const u8;
|
||||
|
||||
|
@ -1000,3 +1011,6 @@ pub extern fn ZigClangParenExpr_getSubExpr(*const ZigClangParenExpr) *const ZigC
|
|||
pub extern fn ZigClangFieldDecl_isBitField(*const struct_ZigClangFieldDecl) bool;
|
||||
pub extern fn ZigClangFieldDecl_getType(*const struct_ZigClangFieldDecl) struct_ZigClangQualType;
|
||||
pub extern fn ZigClangFieldDecl_getLocation(*const struct_ZigClangFieldDecl) struct_ZigClangSourceLocation;
|
||||
|
||||
pub extern fn ZigClangEnumConstantDecl_getInitExpr(*const ZigClangEnumConstantDecl) ?*const ZigClangExpr;
|
||||
pub extern fn ZigClangEnumConstantDecl_getInitVal(*const ZigClangEnumConstantDecl) *const ZigClangAPSInt;
|
||||
|
|
|
@ -15,7 +15,7 @@ pub const Error = error{OutOfMemory};
|
|||
const TypeError = Error || error{UnsupportedType};
|
||||
const TransError = TypeError || error{UnsupportedTranslation};
|
||||
|
||||
const DeclTable = std.HashMap(usize, void, addrHash, addrEql);
|
||||
const DeclTable = std.HashMap(usize, []const u8, addrHash, addrEql);
|
||||
|
||||
fn addrHash(x: usize) u32 {
|
||||
switch (@typeInfo(usize).Int.bits) {
|
||||
|
@ -109,6 +109,12 @@ const Context = struct {
|
|||
global_scope: *Scope.Root,
|
||||
ptr_params: std.BufSet,
|
||||
clang_context: *ZigClangASTContext,
|
||||
mangle_count: u64 = 0,
|
||||
|
||||
fn getMangle(c: *Context) u64 {
|
||||
c.mangle_count += 1;
|
||||
return c.mangle_count;
|
||||
}
|
||||
|
||||
fn a(c: *Context) *std.mem.Allocator {
|
||||
return &c.tree.arena_allocator.allocator;
|
||||
|
@ -239,7 +245,7 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void {
|
|||
return resolveTypeDef(c, @ptrCast(*const ZigClangTypedefNameDecl, decl));
|
||||
},
|
||||
.Enum => {
|
||||
try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for enums", .{});
|
||||
_ = try transEnumDecl(c, @ptrCast(*const ZigClangEnumDecl, decl));
|
||||
},
|
||||
.Record => {
|
||||
return resolveRecordDecl(c, @ptrCast(*const ZigClangRecordDecl, decl));
|
||||
|
@ -255,9 +261,10 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void {
|
|||
}
|
||||
|
||||
fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
|
||||
if (try c.decl_table.put(@ptrToInt(fn_decl), {})) |_| return; // Avoid processing this decl twice
|
||||
if (c.decl_table.contains(@ptrToInt(fn_decl))) return; // Avoid processing this decl twice
|
||||
const rp = makeRestorePoint(c);
|
||||
const fn_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, fn_decl)));
|
||||
_ = try c.decl_table.put(@ptrToInt(fn_decl), fn_name);
|
||||
const fn_decl_loc = ZigClangFunctionDecl_getLocation(fn_decl);
|
||||
const fn_qt = ZigClangFunctionDecl_getType(fn_decl);
|
||||
const fn_type = ZigClangQualType_getTypePtr(fn_qt);
|
||||
|
@ -319,7 +326,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
|
|||
}
|
||||
|
||||
fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
|
||||
if (try c.decl_table.put(@ptrToInt(var_decl), {})) |_| return; // Avoid processing this decl twice
|
||||
if (c.decl_table.contains(@ptrToInt(var_decl))) return; // Avoid processing this decl twice
|
||||
const rp = makeRestorePoint(c);
|
||||
const visib_tok = try appendToken(c, .Keyword_pub, "pub");
|
||||
|
||||
|
@ -330,6 +337,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
|
|||
|
||||
var scope = &c.global_scope.base;
|
||||
const var_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, var_decl)));
|
||||
_ = try c.decl_table.put(@ptrToInt(var_decl), var_name);
|
||||
const var_decl_loc = ZigClangVarDecl_getLocation(var_decl);
|
||||
|
||||
const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl);
|
||||
|
@ -400,12 +408,15 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
|
|||
}
|
||||
|
||||
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
|
||||
if (c.decl_table.contains(
|
||||
@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)));
|
||||
_ = try c.decl_table.put(@ptrToInt(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl)), typedef_name);
|
||||
const name_tok = try appendIdentifier(c, typedef_name);
|
||||
const eq_tok = try appendToken(c, .Equal, "=");
|
||||
|
||||
|
@ -439,7 +450,7 @@ fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Err
|
|||
}
|
||||
|
||||
fn resolveRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!void {
|
||||
if (try c.decl_table.put(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)), {})) |_| return; // Avoid processing this decl twice
|
||||
if (c.decl_table.contains(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)))) return; // Avoid processing this decl twice
|
||||
const rp = makeRestorePoint(c);
|
||||
|
||||
const bare_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, record_decl)));
|
||||
|
@ -449,7 +460,7 @@ fn resolveRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!
|
|||
else if (ZigClangRecordDecl_isStruct(record_decl))
|
||||
"struct"
|
||||
else
|
||||
return failDecl(c, ZigClangRecordDecl_getLocation(record_decl), bare_name, "record {} is not a struct or union", .{bare_name});
|
||||
return emitWarning(c, ZigClangRecordDecl_getLocation(record_decl), "record {} is not a struct or union", .{bare_name});
|
||||
|
||||
if (ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl) or bare_name.len == 0)
|
||||
return;
|
||||
|
@ -458,6 +469,7 @@ fn resolveRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!
|
|||
const const_tok = try appendToken(c, .Keyword_const, "const");
|
||||
|
||||
const name = try std.fmt.allocPrint(c.a(), "{}_{}", .{ container_kind_name, bare_name });
|
||||
_ = try c.decl_table.put(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)), name);
|
||||
const name_tok = try appendIdentifier(c, name);
|
||||
|
||||
const eq_tok = try appendToken(c, .Equal, "=");
|
||||
|
@ -1386,6 +1398,195 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) TypeErro
|
|||
return &container_node.base;
|
||||
}
|
||||
|
||||
fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.Node {
|
||||
if (c.decl_table.get(@ptrToInt(ZigClangEnumDecl_getCanonicalDecl(enum_decl)))) |name|
|
||||
return try transCreateNodeIdentifier(c, name.value); // Avoid processing this decl twice
|
||||
const rp = makeRestorePoint(c);
|
||||
const enum_loc = ZigClangEnumDecl_getLocation(enum_decl);
|
||||
|
||||
const visib_tok = try appendToken(c, .Keyword_pub, "pub");
|
||||
const const_tok = try appendToken(c, .Keyword_const, "const");
|
||||
|
||||
var bare_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, enum_decl)));
|
||||
var is_unnamed = false;
|
||||
if (bare_name.len == 0) {
|
||||
bare_name = try std.fmt.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()});
|
||||
is_unnamed = true;
|
||||
}
|
||||
|
||||
const name = try std.fmt.allocPrint(c.a(), "enum_{}", .{bare_name});
|
||||
_ = try c.decl_table.put(@ptrToInt(ZigClangEnumDecl_getCanonicalDecl(enum_decl)), name);
|
||||
const name_tok = try appendIdentifier(c, name);
|
||||
const eq_tok = try appendToken(c, .Equal, "=");
|
||||
|
||||
const init_node = if (ZigClangEnumDecl_getDefinition(enum_decl)) |enum_def| blk: {
|
||||
var pure_enum = true;
|
||||
var it = ZigClangEnumDecl_enumerator_begin(enum_def);
|
||||
var end_it = ZigClangEnumDecl_enumerator_end(enum_def);
|
||||
while (ZigClangEnumDecl_enumerator_iterator_neq(it, end_it)) : (it = ZigClangEnumDecl_enumerator_iterator_next(it)) {
|
||||
const enum_const = ZigClangEnumDecl_enumerator_iterator_deref(it);
|
||||
if (ZigClangEnumConstantDecl_getInitExpr(enum_const)) |_| {
|
||||
pure_enum = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const extern_tok = try appendToken(c, .Keyword_extern, "extern");
|
||||
const container_tok = try appendToken(c, .Keyword_enum, "enum");
|
||||
|
||||
const container_node = try c.a().create(ast.Node.ContainerDecl);
|
||||
container_node.* = .{
|
||||
.layout_token = extern_tok,
|
||||
.kind_token = container_tok,
|
||||
.init_arg_expr = .None,
|
||||
.fields_and_decls = ast.Node.ContainerDecl.DeclList.init(c.a()),
|
||||
.lbrace_token = undefined,
|
||||
.rbrace_token = undefined,
|
||||
};
|
||||
|
||||
const int_type = ZigClangEnumDecl_getIntegerType(enum_decl);
|
||||
|
||||
// TODO only emit this tag type if the enum tag type is not the default.
|
||||
// I don't know what the default is, need to figure out how clang is deciding.
|
||||
// it appears to at least be different across gcc/msvc
|
||||
if (!isCBuiltinType(int_type, .UInt) and
|
||||
!isCBuiltinType(int_type, .Int))
|
||||
{
|
||||
_ = try appendToken(c, .LParen, "(");
|
||||
container_node.init_arg_expr = .{
|
||||
.Type = transQualType(rp, int_type, enum_loc) catch |err| switch (err) {
|
||||
error.UnsupportedType => {
|
||||
if (is_unnamed) {
|
||||
try emitWarning(c, enum_loc, "unable to translate enum tag type", .{});
|
||||
} else {
|
||||
try failDecl(c, enum_loc, name, "unable to translate enum tag type", .{});
|
||||
}
|
||||
return null;
|
||||
},
|
||||
else => |e| return e,
|
||||
},
|
||||
};
|
||||
_ = try appendToken(c, .RParen, ")");
|
||||
}
|
||||
|
||||
container_node.lbrace_token = try appendToken(c, .LBrace, "{");
|
||||
|
||||
it = ZigClangEnumDecl_enumerator_begin(enum_def);
|
||||
end_it = ZigClangEnumDecl_enumerator_end(enum_def);
|
||||
while (ZigClangEnumDecl_enumerator_iterator_neq(it, end_it)) : (it = ZigClangEnumDecl_enumerator_iterator_next(it)) {
|
||||
const enum_const = ZigClangEnumDecl_enumerator_iterator_deref(it);
|
||||
|
||||
const enum_val_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, enum_const)));
|
||||
|
||||
const field_name = if (!is_unnamed and std.mem.startsWith(u8, enum_val_name, bare_name))
|
||||
enum_val_name[bare_name.len..]
|
||||
else
|
||||
enum_val_name;
|
||||
|
||||
const field_name_tok = try appendIdentifier(c, field_name);
|
||||
|
||||
const int_node = if (!pure_enum) blk: {
|
||||
_ = try appendToken(c, .Colon, "=");
|
||||
break :blk try transCreateNodeAPInt(c, ZigClangEnumConstantDecl_getInitVal(enum_const));
|
||||
} else
|
||||
null;
|
||||
|
||||
const field_node = try c.a().create(ast.Node.ContainerField);
|
||||
field_node.* = .{
|
||||
.doc_comments = null,
|
||||
.comptime_token = null,
|
||||
.name_token = field_name_tok,
|
||||
.type_expr = null,
|
||||
.value_expr = int_node,
|
||||
.align_expr = null,
|
||||
};
|
||||
|
||||
try container_node.fields_and_decls.push(&field_node.base);
|
||||
_ = try appendToken(c, .Comma, ",");
|
||||
// In C each enum value is in the global namespace. So we put them there too.
|
||||
// At this point we can rely on the enum emitting successfully.
|
||||
try addEnumTopLevel(c, name, field_name, enum_val_name);
|
||||
}
|
||||
container_node.rbrace_token = try appendToken(c, .RBrace, "}");
|
||||
|
||||
break :blk &container_node.base;
|
||||
} else
|
||||
try transCreateNodeOpaqueType(c);
|
||||
|
||||
const semicolon_token = try appendToken(c, .Semicolon, ";");
|
||||
|
||||
const node = try c.a().create(ast.Node.VarDecl);
|
||||
node.* = ast.Node.VarDecl{
|
||||
.visib_token = visib_tok,
|
||||
.mut_token = const_tok,
|
||||
.name_token = name_tok,
|
||||
.eq_token = eq_tok,
|
||||
.init_node = init_node,
|
||||
.semicolon_token = semicolon_token,
|
||||
.doc_comments = null,
|
||||
.comptime_token = null,
|
||||
.extern_export_token = null,
|
||||
.thread_local_token = null,
|
||||
.lib_name = null,
|
||||
.type_node = null,
|
||||
.align_node = null,
|
||||
.section_node = null,
|
||||
};
|
||||
|
||||
try addTopLevelDecl(c, name, &node.base);
|
||||
if (!is_unnamed)
|
||||
try c.alias_list.push(.{ .alias = bare_name, .name = name });
|
||||
return transCreateNodeIdentifier(c, name);
|
||||
}
|
||||
|
||||
fn addEnumTopLevel(c: *Context, enum_name: []const u8, field_name: []const u8, enum_val_name: []const u8) !void {
|
||||
const visib_tok = try appendToken(c, .Keyword_pub, "pub");
|
||||
const const_tok = try appendToken(c, .Keyword_const, "const");
|
||||
const name_tok = try appendIdentifier(c, enum_val_name);
|
||||
const eq_tok = try appendToken(c, .Equal, "=");
|
||||
|
||||
const enum_ident = try transCreateNodeIdentifier(c, enum_name);
|
||||
const period_tok = try appendToken(c, .Period, ".");
|
||||
const field_ident = try transCreateNodeIdentifier(c, field_name);
|
||||
|
||||
const field_access_node = try c.a().create(ast.Node.InfixOp);
|
||||
field_access_node.* = .{
|
||||
.op_token = period_tok,
|
||||
.lhs = enum_ident,
|
||||
.op = .Period,
|
||||
.rhs = field_ident,
|
||||
};
|
||||
const semicolon_token = try appendToken(c, .Semicolon, ";");
|
||||
|
||||
const node = try c.a().create(ast.Node.VarDecl);
|
||||
node.* = ast.Node.VarDecl{
|
||||
.visib_token = visib_tok,
|
||||
.mut_token = const_tok,
|
||||
.name_token = name_tok,
|
||||
.eq_token = eq_tok,
|
||||
.init_node = &field_access_node.base,
|
||||
.semicolon_token = semicolon_token,
|
||||
.thread_local_token = null,
|
||||
.doc_comments = null,
|
||||
.comptime_token = null,
|
||||
.extern_export_token = null,
|
||||
.lib_name = null,
|
||||
.type_node = null,
|
||||
.align_node = null,
|
||||
.section_node = null,
|
||||
};
|
||||
|
||||
try addTopLevelDecl(c, field_name, &node.base);
|
||||
}
|
||||
|
||||
fn isCBuiltinType(qt: ZigClangQualType, kind: ZigClangBuiltinTypeKind) bool {
|
||||
const c_type = qualTypeCanon(qt);
|
||||
if (ZigClangType_getTypeClass(c_type) != .Builtin)
|
||||
return false;
|
||||
const builtin_ty = @ptrCast(*const ZigClangBuiltinType, c_type);
|
||||
return ZigClangBuiltinType_getKind(builtin_ty) == kind;
|
||||
}
|
||||
|
||||
fn qualTypeIsPtr(qt: ZigClangQualType) bool {
|
||||
return ZigClangType_getTypeClass(qualTypeCanon(qt)) == .Pointer;
|
||||
}
|
||||
|
@ -1878,10 +2079,25 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
|
|||
else
|
||||
return transRecordDecl(rp.c, record_decl);
|
||||
},
|
||||
.Enum => {
|
||||
const enum_ty = @ptrCast(*const ZigClangEnumType, ty);
|
||||
|
||||
const enum_decl = ZigClangEnumType_getDecl(enum_ty);
|
||||
return (try transEnumDecl(rp.c, enum_decl)) orelse
|
||||
revertAndWarn(rp, error.UnsupportedType, source_loc, "unable to translate enum declaration", .{});
|
||||
},
|
||||
.Elaborated => {
|
||||
const elaborated_ty = @ptrCast(*const ZigClangElaboratedType, ty);
|
||||
return transQualType(rp, ZigClangElaboratedType_getNamedType(elaborated_ty), source_loc);
|
||||
},
|
||||
.Decayed => {
|
||||
const decayed_ty = @ptrCast(*const ZigClangDecayedType, ty);
|
||||
return transQualType(rp, ZigClangDecayedType_getDecayedType(decayed_ty), source_loc);
|
||||
},
|
||||
.Attributed => {
|
||||
const attributed_ty = @ptrCast(*const ZigClangAttributedType, ty);
|
||||
return transQualType(rp, ZigClangAttributedType_getEquivalentType(attributed_ty), source_loc);
|
||||
},
|
||||
else => {
|
||||
const type_name = rp.c.str(ZigClangType_getTypeClassName(ty));
|
||||
return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported type: '{}'", .{type_name});
|
||||
|
@ -2193,8 +2409,19 @@ fn appendTokenFmt(c: *Context, token_id: Token.Id, comptime format: []const u8,
|
|||
return token_index;
|
||||
}
|
||||
|
||||
fn isValidZigIdentifier(name: []const u8) bool {
|
||||
for (name) |c, i| {
|
||||
switch (c) {
|
||||
'_', 'a'...'z', 'A'...'Z' => {},
|
||||
'0'...'9' => if (i == 0) return false,
|
||||
else => return false,
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
fn appendIdentifier(c: *Context, name: []const u8) !ast.TokenIndex {
|
||||
if (std.zig.Token.getKeyword(name)) |_| {
|
||||
if (!isValidZigIdentifier(name) or std.zig.Token.getKeyword(name) != null) {
|
||||
return appendTokenFmt(c, .Identifier, "@\"{}\"", .{name});
|
||||
} else {
|
||||
return appendTokenFmt(c, .Identifier, "{}", .{name});
|
||||
|
|
|
@ -217,6 +217,72 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||
\\pub const OpenGLProcs = union_OpenGLProcs;
|
||||
});
|
||||
|
||||
cases.add_2("enums",
|
||||
\\typedef enum {
|
||||
\\ a,
|
||||
\\ b,
|
||||
\\ c,
|
||||
\\} d;
|
||||
\\enum {
|
||||
\\ e,
|
||||
\\ f = 4,
|
||||
\\ g,
|
||||
\\} h = e;
|
||||
\\struct Baz {
|
||||
\\ enum {
|
||||
\\ i,
|
||||
\\ j,
|
||||
\\ k,
|
||||
\\ } l;
|
||||
\\ d m;
|
||||
\\};
|
||||
\\enum i {
|
||||
\\ n,
|
||||
\\ o,
|
||||
\\ p,
|
||||
\\};
|
||||
, &[_][]const u8{
|
||||
\\pub const a = enum_unnamed_1.a;
|
||||
\\pub const b = enum_unnamed_1.b;
|
||||
\\pub const c = enum_unnamed_1.c;
|
||||
\\pub const enum_unnamed_1 = extern enum {
|
||||
\\ a,
|
||||
\\ b,
|
||||
\\ c,
|
||||
\\};
|
||||
\\pub const d = enum_unnamed_1;
|
||||
\\pub const e = enum_unnamed_2.e;
|
||||
\\pub const f = enum_unnamed_2.f;
|
||||
\\pub const g = enum_unnamed_2.g;
|
||||
\\pub const enum_unnamed_2 = extern enum {
|
||||
\\ e = 0,
|
||||
\\ f = 4,
|
||||
\\ g = 5,
|
||||
\\};
|
||||
\\pub export var h: enum_unnamed_2 = @as(enum_unnamed_2, e);
|
||||
\\pub const i = enum_unnamed_3.i;
|
||||
\\pub const j = enum_unnamed_3.j;
|
||||
\\pub const k = enum_unnamed_3.k;
|
||||
\\pub const enum_unnamed_3 = extern enum {
|
||||
\\ i,
|
||||
\\ j,
|
||||
\\ k,
|
||||
\\};
|
||||
\\pub const struct_Baz = extern struct {
|
||||
\\ l: enum_unnamed_3,
|
||||
\\ m: d,
|
||||
\\};
|
||||
\\pub const n = enum_i.n;
|
||||
\\pub const o = enum_i.o;
|
||||
\\pub const p = enum_i.p;
|
||||
\\pub const enum_i = extern enum {
|
||||
\\ n,
|
||||
\\ o,
|
||||
\\ p,
|
||||
\\};
|
||||
\\pub const Baz = struct_Baz;
|
||||
});
|
||||
|
||||
/////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
|
||||
|
||||
cases.add_both("typedef of function in struct field",
|
||||
|
@ -440,7 +506,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||
\\}
|
||||
});
|
||||
|
||||
cases.add("enums",
|
||||
cases.add_both("enums",
|
||||
\\enum Foo {
|
||||
\\ FooA,
|
||||
\\ FooB,
|
||||
|
@ -462,7 +528,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||
\\pub const Foo = enum_Foo;
|
||||
});
|
||||
|
||||
cases.add("enums",
|
||||
cases.add_both("enums",
|
||||
\\enum Foo {
|
||||
\\ FooA = 2,
|
||||
\\ FooB = 5,
|
||||
|
|
Loading…
Reference in New Issue
Block a user