authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-14 21:46:54+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-14 23:24:47+02:00
loge57e3602e7802789d56a076c6052092715997c24
tree1911b3595996594dffb1390699849c46eba8ad0a
parent1a967db08311cd5046660e9df13a51e622f005b6
signature Commit is signed but in an unrecognized format.

translate-c-2 implement enums


4 files changed, 319 insertions(+), 11 deletions(-)

lib/std/zig/render.zig+1
...@@ -193,6 +193,7 @@ fn renderRoot(...@@ -193,6 +193,7 @@ fn renderRoot(
193fn renderExtraNewline(tree: *ast.Tree, stream: var, start_col: *usize, node: *ast.Node) @TypeOf(stream).Child.Error!void {193fn renderExtraNewline(tree: *ast.Tree, stream: var, start_col: *usize, node: *ast.Node) @TypeOf(stream).Child.Error!void {
194 const first_token = node.firstToken();194 const first_token = node.firstToken();
195 var prev_token = first_token;195 var prev_token = first_token;
196 if (prev_token == 0) return;
196 while (tree.tokens.at(prev_token - 1).id == .DocComment) {197 while (tree.tokens.at(prev_token - 1).id == .DocComment) {
197 prev_token -= 1;198 prev_token -= 1;
198 }199 }
src-self-hosted/clang.zig+15-1
...@@ -713,6 +713,10 @@ pub const ZigClangRecordDecl_field_iterator = extern struct {...@@ -713,6 +713,10 @@ pub const ZigClangRecordDecl_field_iterator = extern struct {
713 opaque: *c_void,713 opaque: *c_void,
714};714};
715715
716pub const ZigClangEnumDecl_enumerator_iterator = extern struct {
717 opaque: *c_void,
718};
719
716pub extern fn ZigClangSourceManager_getSpellingLoc(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) struct_ZigClangSourceLocation;720pub extern fn ZigClangSourceManager_getSpellingLoc(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) struct_ZigClangSourceLocation;
717pub extern fn ZigClangSourceManager_getFilename(self: *const struct_ZigClangSourceManager, SpellingLoc: struct_ZigClangSourceLocation) ?[*:0]const u8;721pub extern fn ZigClangSourceManager_getFilename(self: *const struct_ZigClangSourceManager, SpellingLoc: struct_ZigClangSourceLocation) ?[*:0]const u8;
718pub extern fn ZigClangSourceManager_getSpellingLineNumber(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint;722pub 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...@@ -723,7 +727,7 @@ pub extern fn ZigClangASTUnit_getASTContext(self: ?*struct_ZigClangASTUnit) ?*st
723pub extern fn ZigClangASTUnit_getSourceManager(self: *struct_ZigClangASTUnit) *struct_ZigClangSourceManager;727pub extern fn ZigClangASTUnit_getSourceManager(self: *struct_ZigClangASTUnit) *struct_ZigClangSourceManager;
724pub extern fn ZigClangASTUnit_visitLocalTopLevelDecls(self: *struct_ZigClangASTUnit, context: ?*c_void, Fn: ?extern fn (?*c_void, *const struct_ZigClangDecl) bool) bool;728pub extern fn ZigClangASTUnit_visitLocalTopLevelDecls(self: *struct_ZigClangASTUnit, context: ?*c_void, Fn: ?extern fn (?*c_void, *const struct_ZigClangDecl) bool) bool;
725pub extern fn ZigClangRecordType_getDecl(record_ty: ?*const struct_ZigClangRecordType) *const struct_ZigClangRecordDecl;729pub extern fn ZigClangRecordType_getDecl(record_ty: ?*const struct_ZigClangRecordType) *const struct_ZigClangRecordDecl;
726pub extern fn ZigClangEnumType_getDecl(record_ty: ?*const struct_ZigClangEnumType) ?*const struct_ZigClangEnumDecl;730pub extern fn ZigClangEnumType_getDecl(record_ty: ?*const struct_ZigClangEnumType) *const struct_ZigClangEnumDecl;
727pub extern fn ZigClangRecordDecl_getCanonicalDecl(record_decl: ?*const struct_ZigClangRecordDecl) ?*const struct_ZigClangTagDecl;731pub extern fn ZigClangRecordDecl_getCanonicalDecl(record_decl: ?*const struct_ZigClangRecordDecl) ?*const struct_ZigClangTagDecl;
728pub extern fn ZigClangEnumDecl_getCanonicalDecl(self: ?*const struct_ZigClangEnumDecl) ?*const struct_ZigClangTagDecl;732pub extern fn ZigClangEnumDecl_getCanonicalDecl(self: ?*const struct_ZigClangEnumDecl) ?*const struct_ZigClangTagDecl;
729pub extern fn ZigClangTypedefNameDecl_getCanonicalDecl(self: ?*const struct_ZigClangTypedefNameDecl) ?*const struct_ZigClangTypedefNameDecl;733pub 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...@@ -742,6 +746,11 @@ pub extern fn ZigClangRecordDecl_field_iterator_next(ZigClangRecordDecl_field_it
742pub extern fn ZigClangRecordDecl_field_iterator_deref(ZigClangRecordDecl_field_iterator) *const struct_ZigClangFieldDecl;746pub extern fn ZigClangRecordDecl_field_iterator_deref(ZigClangRecordDecl_field_iterator) *const struct_ZigClangFieldDecl;
743pub extern fn ZigClangRecordDecl_field_iterator_neq(ZigClangRecordDecl_field_iterator, ZigClangRecordDecl_field_iterator) bool;747pub extern fn ZigClangRecordDecl_field_iterator_neq(ZigClangRecordDecl_field_iterator, ZigClangRecordDecl_field_iterator) bool;
744pub extern fn ZigClangEnumDecl_getIntegerType(self: ?*const struct_ZigClangEnumDecl) struct_ZigClangQualType;748pub extern fn ZigClangEnumDecl_getIntegerType(self: ?*const struct_ZigClangEnumDecl) struct_ZigClangQualType;
749pub extern fn ZigClangEnumDecl_enumerator_begin(*const ZigClangEnumDecl) ZigClangEnumDecl_enumerator_iterator;
750pub extern fn ZigClangEnumDecl_enumerator_end(*const ZigClangEnumDecl) ZigClangEnumDecl_enumerator_iterator;
751pub extern fn ZigClangEnumDecl_enumerator_iterator_next(ZigClangEnumDecl_enumerator_iterator) ZigClangEnumDecl_enumerator_iterator;
752pub extern fn ZigClangEnumDecl_enumerator_iterator_deref(ZigClangEnumDecl_enumerator_iterator) *const ZigClangEnumConstantDecl;
753pub extern fn ZigClangEnumDecl_enumerator_iterator_neq(ZigClangEnumDecl_enumerator_iterator, ZigClangEnumDecl_enumerator_iterator) bool;
745pub extern fn ZigClangDecl_getName_bytes_begin(decl: ?*const struct_ZigClangDecl) [*c]const u8;754pub extern fn ZigClangDecl_getName_bytes_begin(decl: ?*const struct_ZigClangDecl) [*c]const u8;
746pub extern fn ZigClangSourceLocation_eq(a: struct_ZigClangSourceLocation, b: struct_ZigClangSourceLocation) bool;755pub extern fn ZigClangSourceLocation_eq(a: struct_ZigClangSourceLocation, b: struct_ZigClangSourceLocation) bool;
747pub extern fn ZigClangTypedefType_getDecl(self: ?*const struct_ZigClangTypedefType) *const struct_ZigClangTypedefNameDecl;756pub extern fn ZigClangTypedefType_getDecl(self: ?*const struct_ZigClangTypedefType) *const struct_ZigClangTypedefNameDecl;
...@@ -992,6 +1001,8 @@ pub extern fn ZigClangBinaryOperator_getLHS(*const ZigClangBinaryOperator) *cons...@@ -992,6 +1001,8 @@ pub extern fn ZigClangBinaryOperator_getLHS(*const ZigClangBinaryOperator) *cons
992pub extern fn ZigClangBinaryOperator_getRHS(*const ZigClangBinaryOperator) *const ZigClangExpr;1001pub extern fn ZigClangBinaryOperator_getRHS(*const ZigClangBinaryOperator) *const ZigClangExpr;
993pub extern fn ZigClangBinaryOperator_getType(*const ZigClangBinaryOperator) ZigClangQualType;1002pub extern fn ZigClangBinaryOperator_getType(*const ZigClangBinaryOperator) ZigClangQualType;
9941003
1004pub extern fn ZigClangDecayedType_getDecayedType(*const ZigClangDecayedType) ZigClangQualType;
1005
995pub extern fn ZigClangStringLiteral_getKind(*const ZigClangStringLiteral) ZigClangStringLiteral_StringKind;1006pub extern fn ZigClangStringLiteral_getKind(*const ZigClangStringLiteral) ZigClangStringLiteral_StringKind;
996pub extern fn ZigClangStringLiteral_getString_bytes_begin_size(*const ZigClangStringLiteral, *usize) [*c]const u8;1007pub extern fn ZigClangStringLiteral_getString_bytes_begin_size(*const ZigClangStringLiteral, *usize) [*c]const u8;
9971008
...@@ -1000,3 +1011,6 @@ pub extern fn ZigClangParenExpr_getSubExpr(*const ZigClangParenExpr) *const ZigC...@@ -1000,3 +1011,6 @@ pub extern fn ZigClangParenExpr_getSubExpr(*const ZigClangParenExpr) *const ZigC
1000pub extern fn ZigClangFieldDecl_isBitField(*const struct_ZigClangFieldDecl) bool;1011pub extern fn ZigClangFieldDecl_isBitField(*const struct_ZigClangFieldDecl) bool;
1001pub extern fn ZigClangFieldDecl_getType(*const struct_ZigClangFieldDecl) struct_ZigClangQualType;1012pub extern fn ZigClangFieldDecl_getType(*const struct_ZigClangFieldDecl) struct_ZigClangQualType;
1002pub extern fn ZigClangFieldDecl_getLocation(*const struct_ZigClangFieldDecl) struct_ZigClangSourceLocation;1013pub extern fn ZigClangFieldDecl_getLocation(*const struct_ZigClangFieldDecl) struct_ZigClangSourceLocation;
1014
1015pub extern fn ZigClangEnumConstantDecl_getInitExpr(*const ZigClangEnumConstantDecl) ?*const ZigClangExpr;
1016pub extern fn ZigClangEnumConstantDecl_getInitVal(*const ZigClangEnumConstantDecl) *const ZigClangAPSInt;
src-self-hosted/translate_c.zig+235-8
...@@ -15,7 +15,7 @@ pub const Error = error{OutOfMemory};...@@ -15,7 +15,7 @@ pub const Error = error{OutOfMemory};
15const TypeError = Error || error{UnsupportedType};15const TypeError = Error || error{UnsupportedType};
16const TransError = TypeError || error{UnsupportedTranslation};16const TransError = TypeError || error{UnsupportedTranslation};
1717
18const DeclTable = std.HashMap(usize, void, addrHash, addrEql);18const DeclTable = std.HashMap(usize, []const u8, addrHash, addrEql);
1919
20fn addrHash(x: usize) u32 {20fn addrHash(x: usize) u32 {
21 switch (@typeInfo(usize).Int.bits) {21 switch (@typeInfo(usize).Int.bits) {
...@@ -109,6 +109,12 @@ const Context = struct {...@@ -109,6 +109,12 @@ const Context = struct {
109 global_scope: *Scope.Root,109 global_scope: *Scope.Root,
110 ptr_params: std.BufSet,110 ptr_params: std.BufSet,
111 clang_context: *ZigClangASTContext,111 clang_context: *ZigClangASTContext,
112 mangle_count: u64 = 0,
113
114 fn getMangle(c: *Context) u64 {
115 c.mangle_count += 1;
116 return c.mangle_count;
117 }
112118
113 fn a(c: *Context) *std.mem.Allocator {119 fn a(c: *Context) *std.mem.Allocator {
114 return &c.tree.arena_allocator.allocator;120 return &c.tree.arena_allocator.allocator;
...@@ -239,7 +245,7 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void {...@@ -239,7 +245,7 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void {
239 return resolveTypeDef(c, @ptrCast(*const ZigClangTypedefNameDecl, decl));245 return resolveTypeDef(c, @ptrCast(*const ZigClangTypedefNameDecl, decl));
240 },246 },
241 .Enum => {247 .Enum => {
242 try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for enums", .{});248 _ = try transEnumDecl(c, @ptrCast(*const ZigClangEnumDecl, decl));
243 },249 },
244 .Record => {250 .Record => {
245 return resolveRecordDecl(c, @ptrCast(*const ZigClangRecordDecl, decl));251 return resolveRecordDecl(c, @ptrCast(*const ZigClangRecordDecl, decl));
...@@ -255,9 +261,10 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void {...@@ -255,9 +261,10 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void {
255}261}
256262
257fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {263fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
258 if (try c.decl_table.put(@ptrToInt(fn_decl), {})) |_| return; // Avoid processing this decl twice264 if (c.decl_table.contains(@ptrToInt(fn_decl))) return; // Avoid processing this decl twice
259 const rp = makeRestorePoint(c);265 const rp = makeRestorePoint(c);
260 const fn_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, fn_decl)));266 const fn_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, fn_decl)));
267 _ = try c.decl_table.put(@ptrToInt(fn_decl), fn_name);
261 const fn_decl_loc = ZigClangFunctionDecl_getLocation(fn_decl);268 const fn_decl_loc = ZigClangFunctionDecl_getLocation(fn_decl);
262 const fn_qt = ZigClangFunctionDecl_getType(fn_decl);269 const fn_qt = ZigClangFunctionDecl_getType(fn_decl);
263 const fn_type = ZigClangQualType_getTypePtr(fn_qt);270 const fn_type = ZigClangQualType_getTypePtr(fn_qt);
...@@ -319,7 +326,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {...@@ -319,7 +326,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
319}326}
320327
321fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {328fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
322 if (try c.decl_table.put(@ptrToInt(var_decl), {})) |_| return; // Avoid processing this decl twice329 if (c.decl_table.contains(@ptrToInt(var_decl))) return; // Avoid processing this decl twice
323 const rp = makeRestorePoint(c);330 const rp = makeRestorePoint(c);
324 const visib_tok = try appendToken(c, .Keyword_pub, "pub");331 const visib_tok = try appendToken(c, .Keyword_pub, "pub");
325332
...@@ -330,6 +337,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {...@@ -330,6 +337,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
330337
331 var scope = &c.global_scope.base;338 var scope = &c.global_scope.base;
332 const var_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, var_decl)));339 const var_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, var_decl)));
340 _ = try c.decl_table.put(@ptrToInt(var_decl), var_name);
333 const var_decl_loc = ZigClangVarDecl_getLocation(var_decl);341 const var_decl_loc = ZigClangVarDecl_getLocation(var_decl);
334342
335 const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl);343 const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl);
...@@ -400,12 +408,15 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {...@@ -400,12 +408,15 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
400}408}
401409
402fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Error!void {410fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Error!void {
403 if (try c.decl_table.put(@ptrToInt(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl)), {})) |_| return; // Avoid processing this decl twice411 if (c.decl_table.contains(
412 @ptrToInt(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl)),
413 )) return; // Avoid processing this decl twice
404 const rp = makeRestorePoint(c);414 const rp = makeRestorePoint(c);
405 const visib_tok = try appendToken(c, .Keyword_pub, "pub");415 const visib_tok = try appendToken(c, .Keyword_pub, "pub");
406 const const_tok = try appendToken(c, .Keyword_const, "const");416 const const_tok = try appendToken(c, .Keyword_const, "const");
407417
408 const typedef_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, typedef_decl)));418 const typedef_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, typedef_decl)));
419 _ = try c.decl_table.put(@ptrToInt(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl)), typedef_name);
409 const name_tok = try appendIdentifier(c, typedef_name);420 const name_tok = try appendIdentifier(c, typedef_name);
410 const eq_tok = try appendToken(c, .Equal, "=");421 const eq_tok = try appendToken(c, .Equal, "=");
411422
...@@ -439,7 +450,7 @@ fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Err...@@ -439,7 +450,7 @@ fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Err
439}450}
440451
441fn resolveRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!void {452fn resolveRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!void {
442 if (try c.decl_table.put(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)), {})) |_| return; // Avoid processing this decl twice453 if (c.decl_table.contains(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)))) return; // Avoid processing this decl twice
443 const rp = makeRestorePoint(c);454 const rp = makeRestorePoint(c);
444455
445 const bare_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, record_decl)));456 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!...@@ -449,7 +460,7 @@ fn resolveRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!
449 else if (ZigClangRecordDecl_isStruct(record_decl))460 else if (ZigClangRecordDecl_isStruct(record_decl))
450 "struct"461 "struct"
451 else462 else
452 return failDecl(c, ZigClangRecordDecl_getLocation(record_decl), bare_name, "record {} is not a struct or union", .{bare_name});463 return emitWarning(c, ZigClangRecordDecl_getLocation(record_decl), "record {} is not a struct or union", .{bare_name});
453464
454 if (ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl) or bare_name.len == 0)465 if (ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl) or bare_name.len == 0)
455 return;466 return;
...@@ -458,6 +469,7 @@ fn resolveRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!...@@ -458,6 +469,7 @@ fn resolveRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!
458 const const_tok = try appendToken(c, .Keyword_const, "const");469 const const_tok = try appendToken(c, .Keyword_const, "const");
459470
460 const name = try std.fmt.allocPrint(c.a(), "{}_{}", .{ container_kind_name, bare_name });471 const name = try std.fmt.allocPrint(c.a(), "{}_{}", .{ container_kind_name, bare_name });
472 _ = try c.decl_table.put(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)), name);
461 const name_tok = try appendIdentifier(c, name);473 const name_tok = try appendIdentifier(c, name);
462474
463 const eq_tok = try appendToken(c, .Equal, "=");475 const eq_tok = try appendToken(c, .Equal, "=");
...@@ -1386,6 +1398,195 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) TypeErro...@@ -1386,6 +1398,195 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) TypeErro
1386 return &container_node.base;1398 return &container_node.base;
1387}1399}
13881400
1401fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.Node {
1402 if (c.decl_table.get(@ptrToInt(ZigClangEnumDecl_getCanonicalDecl(enum_decl)))) |name|
1403 return try transCreateNodeIdentifier(c, name.value); // Avoid processing this decl twice
1404 const rp = makeRestorePoint(c);
1405 const enum_loc = ZigClangEnumDecl_getLocation(enum_decl);
1406
1407 const visib_tok = try appendToken(c, .Keyword_pub, "pub");
1408 const const_tok = try appendToken(c, .Keyword_const, "const");
1409
1410 var bare_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, enum_decl)));
1411 var is_unnamed = false;
1412 if (bare_name.len == 0) {
1413 bare_name = try std.fmt.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()});
1414 is_unnamed = true;
1415 }
1416
1417 const name = try std.fmt.allocPrint(c.a(), "enum_{}", .{bare_name});
1418 _ = try c.decl_table.put(@ptrToInt(ZigClangEnumDecl_getCanonicalDecl(enum_decl)), name);
1419 const name_tok = try appendIdentifier(c, name);
1420 const eq_tok = try appendToken(c, .Equal, "=");
1421
1422 const init_node = if (ZigClangEnumDecl_getDefinition(enum_decl)) |enum_def| blk: {
1423 var pure_enum = true;
1424 var it = ZigClangEnumDecl_enumerator_begin(enum_def);
1425 var end_it = ZigClangEnumDecl_enumerator_end(enum_def);
1426 while (ZigClangEnumDecl_enumerator_iterator_neq(it, end_it)) : (it = ZigClangEnumDecl_enumerator_iterator_next(it)) {
1427 const enum_const = ZigClangEnumDecl_enumerator_iterator_deref(it);
1428 if (ZigClangEnumConstantDecl_getInitExpr(enum_const)) |_| {
1429 pure_enum = false;
1430 break;
1431 }
1432 }
1433
1434 const extern_tok = try appendToken(c, .Keyword_extern, "extern");
1435 const container_tok = try appendToken(c, .Keyword_enum, "enum");
1436
1437 const container_node = try c.a().create(ast.Node.ContainerDecl);
1438 container_node.* = .{
1439 .layout_token = extern_tok,
1440 .kind_token = container_tok,
1441 .init_arg_expr = .None,
1442 .fields_and_decls = ast.Node.ContainerDecl.DeclList.init(c.a()),
1443 .lbrace_token = undefined,
1444 .rbrace_token = undefined,
1445 };
1446
1447 const int_type = ZigClangEnumDecl_getIntegerType(enum_decl);
1448
1449 // TODO only emit this tag type if the enum tag type is not the default.
1450 // I don't know what the default is, need to figure out how clang is deciding.
1451 // it appears to at least be different across gcc/msvc
1452 if (!isCBuiltinType(int_type, .UInt) and
1453 !isCBuiltinType(int_type, .Int))
1454 {
1455 _ = try appendToken(c, .LParen, "(");
1456 container_node.init_arg_expr = .{
1457 .Type = transQualType(rp, int_type, enum_loc) catch |err| switch (err) {
1458 error.UnsupportedType => {
1459 if (is_unnamed) {
1460 try emitWarning(c, enum_loc, "unable to translate enum tag type", .{});
1461 } else {
1462 try failDecl(c, enum_loc, name, "unable to translate enum tag type", .{});
1463 }
1464 return null;
1465 },
1466 else => |e| return e,
1467 },
1468 };
1469 _ = try appendToken(c, .RParen, ")");
1470 }
1471
1472 container_node.lbrace_token = try appendToken(c, .LBrace, "{");
1473
1474 it = ZigClangEnumDecl_enumerator_begin(enum_def);
1475 end_it = ZigClangEnumDecl_enumerator_end(enum_def);
1476 while (ZigClangEnumDecl_enumerator_iterator_neq(it, end_it)) : (it = ZigClangEnumDecl_enumerator_iterator_next(it)) {
1477 const enum_const = ZigClangEnumDecl_enumerator_iterator_deref(it);
1478
1479 const enum_val_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, enum_const)));
1480
1481 const field_name = if (!is_unnamed and std.mem.startsWith(u8, enum_val_name, bare_name))
1482 enum_val_name[bare_name.len..]
1483 else
1484 enum_val_name;
1485
1486 const field_name_tok = try appendIdentifier(c, field_name);
1487
1488 const int_node = if (!pure_enum) blk: {
1489 _ = try appendToken(c, .Colon, "=");
1490 break :blk try transCreateNodeAPInt(c, ZigClangEnumConstantDecl_getInitVal(enum_const));
1491 } else
1492 null;
1493
1494 const field_node = try c.a().create(ast.Node.ContainerField);
1495 field_node.* = .{
1496 .doc_comments = null,
1497 .comptime_token = null,
1498 .name_token = field_name_tok,
1499 .type_expr = null,
1500 .value_expr = int_node,
1501 .align_expr = null,
1502 };
1503
1504 try container_node.fields_and_decls.push(&field_node.base);
1505 _ = try appendToken(c, .Comma, ",");
1506 // In C each enum value is in the global namespace. So we put them there too.
1507 // At this point we can rely on the enum emitting successfully.
1508 try addEnumTopLevel(c, name, field_name, enum_val_name);
1509 }
1510 container_node.rbrace_token = try appendToken(c, .RBrace, "}");
1511
1512 break :blk &container_node.base;
1513 } else
1514 try transCreateNodeOpaqueType(c);
1515
1516 const semicolon_token = try appendToken(c, .Semicolon, ";");
1517
1518 const node = try c.a().create(ast.Node.VarDecl);
1519 node.* = ast.Node.VarDecl{
1520 .visib_token = visib_tok,
1521 .mut_token = const_tok,
1522 .name_token = name_tok,
1523 .eq_token = eq_tok,
1524 .init_node = init_node,
1525 .semicolon_token = semicolon_token,
1526 .doc_comments = null,
1527 .comptime_token = null,
1528 .extern_export_token = null,
1529 .thread_local_token = null,
1530 .lib_name = null,
1531 .type_node = null,
1532 .align_node = null,
1533 .section_node = null,
1534 };
1535
1536 try addTopLevelDecl(c, name, &node.base);
1537 if (!is_unnamed)
1538 try c.alias_list.push(.{ .alias = bare_name, .name = name });
1539 return transCreateNodeIdentifier(c, name);
1540}
1541
1542fn addEnumTopLevel(c: *Context, enum_name: []const u8, field_name: []const u8, enum_val_name: []const u8) !void {
1543 const visib_tok = try appendToken(c, .Keyword_pub, "pub");
1544 const const_tok = try appendToken(c, .Keyword_const, "const");
1545 const name_tok = try appendIdentifier(c, enum_val_name);
1546 const eq_tok = try appendToken(c, .Equal, "=");
1547
1548 const enum_ident = try transCreateNodeIdentifier(c, enum_name);
1549 const period_tok = try appendToken(c, .Period, ".");
1550 const field_ident = try transCreateNodeIdentifier(c, field_name);
1551
1552 const field_access_node = try c.a().create(ast.Node.InfixOp);
1553 field_access_node.* = .{
1554 .op_token = period_tok,
1555 .lhs = enum_ident,
1556 .op = .Period,
1557 .rhs = field_ident,
1558 };
1559 const semicolon_token = try appendToken(c, .Semicolon, ";");
1560
1561 const node = try c.a().create(ast.Node.VarDecl);
1562 node.* = ast.Node.VarDecl{
1563 .visib_token = visib_tok,
1564 .mut_token = const_tok,
1565 .name_token = name_tok,
1566 .eq_token = eq_tok,
1567 .init_node = &field_access_node.base,
1568 .semicolon_token = semicolon_token,
1569 .thread_local_token = null,
1570 .doc_comments = null,
1571 .comptime_token = null,
1572 .extern_export_token = null,
1573 .lib_name = null,
1574 .type_node = null,
1575 .align_node = null,
1576 .section_node = null,
1577 };
1578
1579 try addTopLevelDecl(c, field_name, &node.base);
1580}
1581
1582fn isCBuiltinType(qt: ZigClangQualType, kind: ZigClangBuiltinTypeKind) bool {
1583 const c_type = qualTypeCanon(qt);
1584 if (ZigClangType_getTypeClass(c_type) != .Builtin)
1585 return false;
1586 const builtin_ty = @ptrCast(*const ZigClangBuiltinType, c_type);
1587 return ZigClangBuiltinType_getKind(builtin_ty) == kind;
1588}
1589
1389fn qualTypeIsPtr(qt: ZigClangQualType) bool {1590fn qualTypeIsPtr(qt: ZigClangQualType) bool {
1390 return ZigClangType_getTypeClass(qualTypeCanon(qt)) == .Pointer;1591 return ZigClangType_getTypeClass(qualTypeCanon(qt)) == .Pointer;
1391}1592}
...@@ -1878,10 +2079,25 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour...@@ -1878,10 +2079,25 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
1878 else2079 else
1879 return transRecordDecl(rp.c, record_decl);2080 return transRecordDecl(rp.c, record_decl);
1880 },2081 },
2082 .Enum => {
2083 const enum_ty = @ptrCast(*const ZigClangEnumType, ty);
2084
2085 const enum_decl = ZigClangEnumType_getDecl(enum_ty);
2086 return (try transEnumDecl(rp.c, enum_decl)) orelse
2087 revertAndWarn(rp, error.UnsupportedType, source_loc, "unable to translate enum declaration", .{});
2088 },
1881 .Elaborated => {2089 .Elaborated => {
1882 const elaborated_ty = @ptrCast(*const ZigClangElaboratedType, ty);2090 const elaborated_ty = @ptrCast(*const ZigClangElaboratedType, ty);
1883 return transQualType(rp, ZigClangElaboratedType_getNamedType(elaborated_ty), source_loc);2091 return transQualType(rp, ZigClangElaboratedType_getNamedType(elaborated_ty), source_loc);
1884 },2092 },
2093 .Decayed => {
2094 const decayed_ty = @ptrCast(*const ZigClangDecayedType, ty);
2095 return transQualType(rp, ZigClangDecayedType_getDecayedType(decayed_ty), source_loc);
2096 },
2097 .Attributed => {
2098 const attributed_ty = @ptrCast(*const ZigClangAttributedType, ty);
2099 return transQualType(rp, ZigClangAttributedType_getEquivalentType(attributed_ty), source_loc);
2100 },
1885 else => {2101 else => {
1886 const type_name = rp.c.str(ZigClangType_getTypeClassName(ty));2102 const type_name = rp.c.str(ZigClangType_getTypeClassName(ty));
1887 return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported type: '{}'", .{type_name});2103 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,...@@ -2193,8 +2409,19 @@ fn appendTokenFmt(c: *Context, token_id: Token.Id, comptime format: []const u8,
2193 return token_index;2409 return token_index;
2194}2410}
21952411
2412fn isValidZigIdentifier(name: []const u8) bool {
2413 for (name) |c, i| {
2414 switch (c) {
2415 '_', 'a'...'z', 'A'...'Z' => {},
2416 '0'...'9' => if (i == 0) return false,
2417 else => return false,
2418 }
2419 }
2420 return true;
2421}
2422
2196fn appendIdentifier(c: *Context, name: []const u8) !ast.TokenIndex {2423fn appendIdentifier(c: *Context, name: []const u8) !ast.TokenIndex {
2197 if (std.zig.Token.getKeyword(name)) |_| {2424 if (!isValidZigIdentifier(name) or std.zig.Token.getKeyword(name) != null) {
2198 return appendTokenFmt(c, .Identifier, "@\"{}\"", .{name});2425 return appendTokenFmt(c, .Identifier, "@\"{}\"", .{name});
2199 } else {2426 } else {
2200 return appendTokenFmt(c, .Identifier, "{}", .{name});2427 return appendTokenFmt(c, .Identifier, "{}", .{name});
test/translate_c.zig+68-2
...@@ -217,6 +217,72 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -217,6 +217,72 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
217 \\pub const OpenGLProcs = union_OpenGLProcs;217 \\pub const OpenGLProcs = union_OpenGLProcs;
218 });218 });
219219
220 cases.add_2("enums",
221 \\typedef enum {
222 \\ a,
223 \\ b,
224 \\ c,
225 \\} d;
226 \\enum {
227 \\ e,
228 \\ f = 4,
229 \\ g,
230 \\} h = e;
231 \\struct Baz {
232 \\ enum {
233 \\ i,
234 \\ j,
235 \\ k,
236 \\ } l;
237 \\ d m;
238 \\};
239 \\enum i {
240 \\ n,
241 \\ o,
242 \\ p,
243 \\};
244 , &[_][]const u8{
245 \\pub const a = enum_unnamed_1.a;
246 \\pub const b = enum_unnamed_1.b;
247 \\pub const c = enum_unnamed_1.c;
248 \\pub const enum_unnamed_1 = extern enum {
249 \\ a,
250 \\ b,
251 \\ c,
252 \\};
253 \\pub const d = enum_unnamed_1;
254 \\pub const e = enum_unnamed_2.e;
255 \\pub const f = enum_unnamed_2.f;
256 \\pub const g = enum_unnamed_2.g;
257 \\pub const enum_unnamed_2 = extern enum {
258 \\ e = 0,
259 \\ f = 4,
260 \\ g = 5,
261 \\};
262 \\pub export var h: enum_unnamed_2 = @as(enum_unnamed_2, e);
263 \\pub const i = enum_unnamed_3.i;
264 \\pub const j = enum_unnamed_3.j;
265 \\pub const k = enum_unnamed_3.k;
266 \\pub const enum_unnamed_3 = extern enum {
267 \\ i,
268 \\ j,
269 \\ k,
270 \\};
271 \\pub const struct_Baz = extern struct {
272 \\ l: enum_unnamed_3,
273 \\ m: d,
274 \\};
275 \\pub const n = enum_i.n;
276 \\pub const o = enum_i.o;
277 \\pub const p = enum_i.p;
278 \\pub const enum_i = extern enum {
279 \\ n,
280 \\ o,
281 \\ p,
282 \\};
283 \\pub const Baz = struct_Baz;
284 });
285
220 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////286 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
221287
222 cases.add_both("typedef of function in struct field",288 cases.add_both("typedef of function in struct field",
...@@ -440,7 +506,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -440,7 +506,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
440 \\}506 \\}
441 });507 });
442508
443 cases.add("enums",509 cases.add_both("enums",
444 \\enum Foo {510 \\enum Foo {
445 \\ FooA,511 \\ FooA,
446 \\ FooB,512 \\ FooB,
...@@ -462,7 +528,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -462,7 +528,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
462 \\pub const Foo = enum_Foo;528 \\pub const Foo = enum_Foo;
463 });529 });
464530
465 cases.add("enums",531 cases.add_both("enums",
466 \\enum Foo {532 \\enum Foo {
467 \\ FooA = 2,533 \\ FooA = 2,
468 \\ FooB = 5,534 \\ FooB = 5,