From 69dee57d95271169898f8382f7e4846bf77a0040 Mon Sep 17 00:00:00 2001 From: Vexu Date: Thu, 12 Dec 2019 14:26:24 +0200 Subject: [PATCH 1/8] remove concept of translate mode --- src-self-hosted/stage1.zig | 12 +----------- src-self-hosted/translate_c.zig | 10 +--------- src/codegen.cpp | 10 +++------- src/ir.cpp | 2 +- src/translate_c.cpp | 21 ++++++--------------- src/translate_c.hpp | 2 +- src/userland.cpp | 3 +-- src/userland.h | 9 +-------- 8 files changed, 15 insertions(+), 54 deletions(-) diff --git a/src-self-hosted/stage1.zig b/src-self-hosted/stage1.zig index 1747e049da..baa4c17ed0 100644 --- a/src-self-hosted/stage1.zig +++ b/src-self-hosted/stage1.zig @@ -33,12 +33,6 @@ export fn stage2_panic(ptr: [*]const u8, len: usize) void { @panic(ptr[0..len]); } -// ABI warning -const TranslateMode = extern enum { - import, - translate, -}; - // ABI warning const Error = extern enum { None, @@ -99,14 +93,10 @@ export fn stage2_translate_c( out_errors_len: *usize, args_begin: [*]?[*]const u8, args_end: [*]?[*]const u8, - mode: TranslateMode, resources_path: [*]const u8, ) Error { var errors: []translate_c.ClangErrMsg = undefined; - out_ast.* = translate_c.translate(std.heap.c_allocator, args_begin, args_end, switch (mode) { - .import => translate_c.Mode.import, - .translate => translate_c.Mode.translate, - }, &errors, resources_path) catch |err| switch (err) { + out_ast.* = translate_c.translate(std.heap.c_allocator, args_begin, args_end, &errors, resources_path) catch |err| switch (err) { error.SemanticAnalyzeFail => { out_errors_ptr.* = errors.ptr; out_errors_len.* = errors.len; diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index 384c4fc147..d4a783634c 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -7,11 +7,6 @@ const ast = std.zig.ast; const Token = std.zig.Token; usingnamespace @import("clang.zig"); -pub const Mode = enum { - import, - translate, -}; - const CallingConvention = std.builtin.TypeInfo.CallingConvention; pub const ClangErrMsg = Stage2ErrorMsg; @@ -104,7 +99,6 @@ const Context = struct { source_manager: *ZigClangSourceManager, decl_table: DeclTable, global_scope: *Scope.Root, - mode: Mode, ptr_params: std.BufSet, clang_context: *ZigClangASTContext, @@ -133,7 +127,6 @@ pub fn translate( backing_allocator: *std.mem.Allocator, args_begin: [*]?[*]const u8, args_end: [*]?[*]const u8, - mode: Mode, errors: *[]ClangErrMsg, resources_path: [*]const u8, ) !*ast.Tree { @@ -185,7 +178,6 @@ pub fn translate( .err = undefined, .decl_table = DeclTable.init(arena), .global_scope = try arena.create(Scope.Root), - .mode = mode, .ptr_params = std.BufSet.init(arena), .clang_context = ZigClangASTUnit_getASTContext(ast_unit).?, }; @@ -262,7 +254,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { .storage_class = storage_class, .scope = &scope, .is_export = switch (storage_class) { - .None => has_body and c.mode != .import, + .None => has_body, .Extern, .Static => false, .PrivateExtern => return failDecl(c, fn_decl_loc, fn_name, "unsupported storage class: private extern", .{}), .Auto => unreachable, // Not legal on functions diff --git a/src/codegen.cpp b/src/codegen.cpp index 5b0899544d..0ba2c23dbe 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -9020,10 +9020,6 @@ void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_us init(g); - Stage2TranslateMode trans_mode = buf_ends_with_str(full_path, ".h") ? - Stage2TranslateModeImport : Stage2TranslateModeTranslate; - - ZigList clang_argv = {0}; add_cc_args(g, clang_argv, nullptr, true); @@ -9047,10 +9043,10 @@ void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_us if (use_userland_implementation) { err = stage2_translate_c(&ast, &errors_ptr, &errors_len, - &clang_argv.at(0), &clang_argv.last(), trans_mode, resources_path); + &clang_argv.at(0), &clang_argv.last(), resources_path); } else { - err = parse_h_file(g, &root_node, &errors_ptr, &errors_len, &clang_argv.at(0), &clang_argv.last(), - trans_mode, resources_path); + err = parse_h_file(g, &root_node, &errors_ptr, &errors_len, &clang_argv.at(0), + &clang_argv.last(), resources_path); } if (err == ErrorCCompileErrors && errors_len > 0) { diff --git a/src/ir.cpp b/src/ir.cpp index 8b588b5dee..cb854303e4 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -23343,7 +23343,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct const char *resources_path = buf_ptr(ira->codegen->zig_c_headers_dir); if ((err = parse_h_file(ira->codegen, &root_node, &errors_ptr, &errors_len, - &clang_argv.at(0), &clang_argv.last(), Stage2TranslateModeImport, resources_path))) + &clang_argv.at(0), &clang_argv.last(), resources_path))) { if (err != ErrorCCompileErrors) { ir_add_error_node(ira, node, buf_sprintf("C import failed: %s", err_str(err))); diff --git a/src/translate_c.cpp b/src/translate_c.cpp index eb207231f0..35830e2990 100644 --- a/src/translate_c.cpp +++ b/src/translate_c.cpp @@ -64,8 +64,6 @@ struct TransScopeWhile { struct Context { AstNode *root; - VisibMod visib_mod; - bool want_export; HashMap decl_table; HashMap macro_table; HashMap global_table; @@ -367,7 +365,7 @@ static AstNode *trans_create_node_var_decl(Context *c, VisibMod visib_mod, bool static AstNode *trans_create_node_var_decl_global(Context *c, bool is_const, Buf *var_name, AstNode *type_node, AstNode *init_node) { - return trans_create_node_var_decl(c, c->visib_mod, is_const, var_name, type_node, init_node); + return trans_create_node_var_decl(c, VisibModPub, is_const, var_name, type_node, init_node); } static AstNode *trans_create_node_var_decl_local(Context *c, bool is_const, Buf *var_name, AstNode *type_node, @@ -379,7 +377,7 @@ static AstNode *trans_create_node_var_decl_local(Context *c, bool is_const, Buf static AstNode *trans_create_node_inline_fn(Context *c, Buf *fn_name, AstNode *ref_node, AstNode *src_proto_node) { AstNode *fn_def = trans_create_node(c, NodeTypeFnDef); AstNode *fn_proto = trans_create_node(c, NodeTypeFnProto); - fn_proto->data.fn_proto.visib_mod = c->visib_mod; + fn_proto->data.fn_proto.visib_mod = VisibModPub; fn_proto->data.fn_proto.name = fn_name; fn_proto->data.fn_proto.fn_inline = FnInlineAlways; fn_proto->data.fn_proto.return_type = src_proto_node->data.fn_proto.return_type; // TODO ok for these to alias? @@ -4091,10 +4089,10 @@ static void visit_fn_decl(Context *c, const ZigClangFunctionDecl *fn_decl) { ZigClangStorageClass sc = ZigClangFunctionDecl_getStorageClass(fn_decl); if (sc == ZigClangStorageClass_None) { - proto_node->data.fn_proto.visib_mod = c->visib_mod; - proto_node->data.fn_proto.is_export = ZigClangFunctionDecl_hasBody(fn_decl) ? c->want_export : false; + proto_node->data.fn_proto.visib_mod = VisibModPub; + proto_node->data.fn_proto.is_export = ZigClangFunctionDecl_hasBody(fn_decl); } else if (sc == ZigClangStorageClass_Extern || sc == ZigClangStorageClass_Static) { - proto_node->data.fn_proto.visib_mod = c->visib_mod; + proto_node->data.fn_proto.visib_mod = VisibModPub; } else if (sc == ZigClangStorageClass_PrivateExtern) { emit_warning(c, ZigClangFunctionDecl_getLocation(fn_decl), "unsupported storage class: private extern"); return; @@ -5113,18 +5111,11 @@ static void process_preprocessor_entities(Context *c, ZigClangASTUnit *unit) { Error parse_h_file(CodeGen *codegen, AstNode **out_root_node, Stage2ErrorMsg **errors_ptr, size_t *errors_len, const char **args_begin, const char **args_end, - Stage2TranslateMode mode, const char *resources_path) + const char *resources_path) { Context context = {0}; Context *c = &context; c->warnings_on = codegen->verbose_cimport; - if (mode == Stage2TranslateModeImport) { - c->visib_mod = VisibModPub; - c->want_export = false; - } else { - c->visib_mod = VisibModPub; - c->want_export = true; - } c->decl_table.init(8); c->macro_table.init(8); c->global_table.init(8); diff --git a/src/translate_c.hpp b/src/translate_c.hpp index 4eac26ddb5..5b7f1dcdd6 100644 --- a/src/translate_c.hpp +++ b/src/translate_c.hpp @@ -14,6 +14,6 @@ Error parse_h_file(CodeGen *codegen, AstNode **out_root_node, Stage2ErrorMsg **errors_ptr, size_t *errors_len, const char **args_begin, const char **args_end, - Stage2TranslateMode mode, const char *resources_path); + const char *resources_path); #endif diff --git a/src/userland.cpp b/src/userland.cpp index a36dfa69a8..263ef0cbc3 100644 --- a/src/userland.cpp +++ b/src/userland.cpp @@ -9,8 +9,7 @@ Error stage2_translate_c(struct Stage2Ast **out_ast, struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len, - const char **args_begin, const char **args_end, enum Stage2TranslateMode mode, - const char *resources_path) + const char **args_begin, const char **args_end, const char *resources_path) { const char *msg = "stage0 called stage2_translate_c"; stage2_panic(msg, strlen(msg)); diff --git a/src/userland.h b/src/userland.h index 1d01257175..fe3f072ae5 100644 --- a/src/userland.h +++ b/src/userland.h @@ -80,12 +80,6 @@ enum Error { ErrorImportOutsidePkgPath, }; -// ABI warning -enum Stage2TranslateMode { - Stage2TranslateModeImport, - Stage2TranslateModeTranslate, -}; - // ABI warning struct Stage2ErrorMsg { const char *filename_ptr; // can be null @@ -104,8 +98,7 @@ struct Stage2Ast; // ABI warning ZIG_EXTERN_C enum Error stage2_translate_c(struct Stage2Ast **out_ast, struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len, - const char **args_begin, const char **args_end, enum Stage2TranslateMode mode, - const char *resources_path); + const char **args_begin, const char **args_end, const char *resources_path); // ABI warning ZIG_EXTERN_C void stage2_free_clang_errors(struct Stage2ErrorMsg *ptr, size_t len); From ef361161e2d6e5d23ee7e8d0fc924e16cf691173 Mon Sep 17 00:00:00 2001 From: Vexu Date: Thu, 12 Dec 2019 16:12:19 +0200 Subject: [PATCH 2/8] translate-c-2 add var decl --- src-self-hosted/clang.zig | 5 ++ src-self-hosted/translate_c.zig | 120 +++++++++++++++++++++++++++++++- 2 files changed, 124 insertions(+), 1 deletion(-) diff --git a/src-self-hosted/clang.zig b/src-self-hosted/clang.zig index 1c8c0928b3..3b498ffdab 100644 --- a/src-self-hosted/clang.zig +++ b/src-self-hosted/clang.zig @@ -916,6 +916,10 @@ pub const ZigClangDeclStmt_const_decl_iterator = [*c]const *struct_ZigClangDecl; pub extern fn ZigClangDeclStmt_decl_begin(self: *const ZigClangDeclStmt) ZigClangDeclStmt_const_decl_iterator; pub extern fn ZigClangDeclStmt_decl_end(self: *const ZigClangDeclStmt) ZigClangDeclStmt_const_decl_iterator; +pub extern fn ZigClangVarDecl_getLocation(self: *const struct_ZigClangVarDecl) ZigClangSourceLocation; +pub extern fn ZigClangVarDecl_hasExternalStorage(self: *const struct_ZigClangVarDecl) bool; +pub extern fn ZigClangVarDecl_isFileVarDecl(self: *const struct_ZigClangVarDecl) bool; +pub extern fn ZigClangVarDecl_hasInit(self: *const struct_ZigClangVarDecl) bool; pub extern fn ZigClangVarDecl_getType(self: ?*const struct_ZigClangVarDecl) struct_ZigClangQualType; pub extern fn ZigClangVarDecl_getInit(*const ZigClangVarDecl) ?*const ZigClangExpr; pub extern fn ZigClangVarDecl_getTLSKind(self: ?*const struct_ZigClangVarDecl) ZigClangVarDecl_TLSKind; @@ -953,6 +957,7 @@ pub const struct_ZigClangExprEvalResult = extern struct { Val: ZigClangAPValue, }; +pub extern fn ZigClangVarDecl_evaluateValue(self: *const struct_ZigClangVarDecl) ?*const ZigClangAPValue; pub const struct_ZigClangAPValue = extern struct { Kind: ZigClangAPValueKind, Data: if (builtin.os == .windows and builtin.abi == .msvc) [52]u8 else [68]u8, diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index d4a783634c..e370678dac 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -229,7 +229,7 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void { try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for structs", .{}); }, .Var => { - try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for variables", .{}); + return visitVarDecl(c, @ptrCast(*const ZigClangVarDecl, decl)); }, else => { const decl_name = try c.str(ZigClangDecl_getDeclKindName(decl)); @@ -302,6 +302,59 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { return addTopLevelDecl(c, fn_name, &proto_node.base); } +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 + const rp = makeRestorePoint(c); + var scope = &c.global_scope.base; + const var_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, var_decl))); + const var_decl_loc = ZigClangVarDecl_getLocation(var_decl); + + switch (ZigClangVarDecl_getTLSKind(var_decl)) { + .None => {}, + .Static => return failDecl(c, var_decl_loc, var_name, "static thread local storage not supported", .{}), + .Dynamic => return failDecl(c, var_decl_loc, var_name, "dynamic thread local storag not supported", .{}), + } + + const qual_type = ZigClangVarDecl_getType(var_decl); + const is_extern = ZigClangVarDecl_hasExternalStorage(var_decl); + const is_static = ZigClangVarDecl_isFileVarDecl(var_decl); + const is_const = ZigClangQualType_isConstQualified(qual_type); + + var var_node = try transCreateNodeVarDecl(c, true, is_extern, is_const, var_name); + + const type_node = transQualType(rp, qual_type, var_decl_loc) catch |err| switch (err) { + error.UnsupportedType => { + return failDecl(c, var_decl_loc, var_name, "unable to resolve variable type", .{}); + }, + error.OutOfMemory => |e| return e, + }; + + if (is_static and !is_extern) { + const eq_tok = try appendToken(c, .Equal, "="); + const init_node = if (ZigClangVarDecl_hasInit(var_decl)) blk: { + const ap_value = ZigClangVarDecl_evaluateValue(var_decl) orelse + return failDecl(c, var_decl_loc, var_name, "unable to evaluate initializer", .{}); + break :blk transApValue(rp, ap_value, qual_type, var_decl_loc) catch |err| switch (err) { + error.UnsupportedTranslation, + error.UnsupportedType, => { + return failDecl(c, var_decl_loc, var_name, "unable to evaluate initializer", .{}); + }, + error.OutOfMemory => |e| return e, + }; + } else + try transCreateNodeUndefinedLiteral(c); + var_node.eq_token = eq_tok; + var_node.init_node = init_node; + } + + if (!is_extern) { + return failDecl(c, var_decl_loc, var_name, "non-extern, non-static variable not supported", .{}); + } + + var_node.semicolon_token = try appendToken(rp.c, .Semicolon, ";"); + return addTopLevelDecl(c, var_name, &var_node.base); +} + const ResultUsed = enum { used, unused, @@ -1225,6 +1278,61 @@ fn transCreateNodeReturnExpr(c: *Context) !*ast.Node { return &node.base; } +fn transCreateNodeUndefinedLiteral(c: *Context) !*ast.Node { + const token = try appendToken(c, .Keyword_undefined, "undefined"); + const node = try c.a().create(ast.Node.UndefinedLiteral); + node.* = ast.Node.UndefinedLiteral{ + .base = ast.Node{ .id = .UndefinedLiteral }, + .token = token, + }; + return &node.base; +} + +fn transCreateNodeVarDecl( + c: *Context, + is_pub: bool, + is_extern: bool, + is_const: bool, + var_name: []const u8, +) !*ast.Node.VarDecl { + const visb_tok = if (is_pub) + try appendToken(c, .Keyword_pub, "pub") + else + null; + + const extern_tok = if (is_extern) + try appendToken(c, .Keyword_extern, "extern") + else + null; + + const mut_tok = if (is_const) + try appendToken(c, .Keyword_const, "const") + else + try appendToken(c, .Keyword_var, "var"); + + const name_tok = try appendToken(c, .Identifier, var_name); + + const node = try c.a().create(ast.Node.VarDecl); + node.* = ast.Node.VarDecl{ + .base = ast.Node{ .id = .VarDecl }, + .doc_comments = null, + .visib_token = visb_tok, + .thread_local_token = null, + .name_token = name_tok, + .eq_token = undefined, // set by caller + .mut_token = mut_tok, + .comptime_token = null, + .extern_export_token = extern_tok, + .lib_name = null, + .type_node = null, + .align_node = null, + .section_node = null, + .init_node = null, + .semicolon_token = undefined, // set by caller + }; + return node; +} + const RestorePoint = struct { c: *Context, token_index: ast.TokenIndex, @@ -1315,6 +1423,16 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour } } +fn transApValue(rp: RestorePoint, ap_value: *const ZigClangAPValue, qual_type: ZigClangQualType, source_loc: ZigClangSourceLocation) TransError!*ast.Node { + return revertAndWarn( + rp, + error.UnsupportedTranslation, + source_loc, + "TODO implement translation of ap value", + .{}, + ); +} + const FnDeclContext = struct { fn_name: []const u8, has_body: bool, From 3bca02509163b1c77776762d371fd802073ff7dd Mon Sep 17 00:00:00 2001 From: Vexu Date: Thu, 12 Dec 2019 16:56:21 +0200 Subject: [PATCH 3/8] update tests --- src-self-hosted/translate_c.zig | 10 +- test/tests.zig | 34 ----- test/translate_c.zig | 219 ++++++++++++++++---------------- 3 files changed, 112 insertions(+), 151 deletions(-) diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index e370678dac..a29755aaba 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -322,7 +322,8 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { var var_node = try transCreateNodeVarDecl(c, true, is_extern, is_const, var_name); - const type_node = transQualType(rp, qual_type, var_decl_loc) catch |err| switch (err) { + _= try appendToken(rp.c, .Colon, ":"); + var_node.type_node = transQualType(rp, qual_type, var_decl_loc) catch |err| switch (err) { error.UnsupportedType => { return failDecl(c, var_decl_loc, var_name, "unable to resolve variable type", .{}); }, @@ -336,7 +337,8 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { return failDecl(c, var_decl_loc, var_name, "unable to evaluate initializer", .{}); break :blk transApValue(rp, ap_value, qual_type, var_decl_loc) catch |err| switch (err) { error.UnsupportedTranslation, - error.UnsupportedType, => { + error.UnsupportedType, + => { return failDecl(c, var_decl_loc, var_name, "unable to evaluate initializer", .{}); }, error.OutOfMemory => |e| return e, @@ -345,9 +347,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { try transCreateNodeUndefinedLiteral(c); var_node.eq_token = eq_tok; var_node.init_node = init_node; - } - - if (!is_extern) { + } else if (!is_extern) { return failDecl(c, var_decl_loc, var_name, "non-extern, non-static variable not supported", .{}); } diff --git a/test/tests.zig b/test/tests.zig index 7326b62054..081136ccad 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -1604,16 +1604,6 @@ pub const TranslateCContext = struct { self.addCase(tc); } - pub fn addC( - self: *TranslateCContext, - name: []const u8, - source: []const u8, - expected_lines: []const []const u8, - ) void { - const tc = self.create(false, "source.c", name, source, expected_lines); - self.addCase(tc); - } - pub fn add_both( self: *TranslateCContext, name: []const u8, @@ -1627,19 +1617,6 @@ pub const TranslateCContext = struct { } } - pub fn addC_both( - self: *TranslateCContext, - name: []const u8, - source: []const u8, - expected_lines: []const []const u8, - ) void { - for ([_]bool{ false, true }) |stage2| { - const tc = self.create(false, "source.c", name, source, expected_lines); - tc.stage2 = stage2; - self.addCase(tc); - } - } - pub fn add_2( self: *TranslateCContext, name: []const u8, @@ -1651,17 +1628,6 @@ pub const TranslateCContext = struct { self.addCase(tc); } - pub fn addC_2( - self: *TranslateCContext, - name: []const u8, - source: []const u8, - expected_lines: []const []const u8, - ) void { - const tc = self.create(false, "source.c", name, source, expected_lines); - tc.stage2 = true; - self.addCase(tc); - } - pub fn addAllowWarnings( self: *TranslateCContext, name: []const u8, diff --git a/test/translate_c.zig b/test/translate_c.zig index 7bd372eb50..5772763a65 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -4,11 +4,8 @@ const builtin = @import("builtin"); // add_both - test for stage1 and stage2, in #include mode // add - test stage1 only, in #include mode // add_2 - test stage2 only, in #include mode -// addC_both - test for stage1 and stage2, in -c mode -// addC - test stage1 only, in -c mode -// addC_2 - test stage2 only, in -c mode -pub fn addCases(cases: *tests.TranslateCContext) void { +pub export fn addCases(cases: *tests.TranslateCContext) void { /////////////// Cases that pass for both stage1/stage2 //////////////// cases.add_both("simple function prototypes", \\void __attribute__((noreturn)) foo(void); @@ -26,7 +23,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ const unsigned d = 440; \\} , &[_][]const u8{ - \\pub fn foo() void { + \\pub export fn foo() void { \\ var a: c_int = undefined; \\ var b: u8 = @as(u8, 123); \\ const c: c_int = undefined; @@ -44,7 +41,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ a = 1; \\} , &[_][]const u8{ - \\pub fn foo() void { + \\pub export fn foo() void { \\ var a: c_int = undefined; \\ _ = 1; \\ _ = "hey"; @@ -54,29 +51,42 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); + cases.add_both("variables", + \\extern int extern_var; + \\static const int int_var = 13; + , &[_][]const u8{ + \\pub extern var extern_var: c_int; + , + \\pub const int_var: c_int = 13; + }); + + cases.add_both("const ptr initializer", + \\static const char *v0 = "0.0.0"; + , &[_][]const u8{ + \\pub var v0: [*c]const u8 = "0.0.0"; + }); + /////////////// Cases that pass for only stage2 //////////////// - // TODO: restore these tests after removing "import mode" concept - // https://github.com/ziglang/zig/issues/2780 - // cases.add_2("Parameterless function prototypes", - // \\void a() {} - // \\void b(void) {} - // \\void c(); - // \\void d(void); - // , - // \\pub export fn a() void {} - // \\pub export fn b() void {} - // \\pub extern fn c(...) void; - // \\pub extern fn d() void; - // ); + cases.add_2("Parameterless function prototypes", + \\void a() {} + \\void b(void) {} + \\void c(); + \\void d(void); + , &[_][]const u8{ + \\pub export fn a() void {} + \\pub export fn b() void {} + \\pub extern fn c(...) void; + \\pub extern fn d() void; + }); - // cases.add_2("simple function definition", - // \\void foo(void) {} - // \\static void bar(void) {} - // , - // \\pub export fn foo() void {} - // \\pub extern fn bar() void {} - // ); + cases.add_2("simple function definition", + \\void foo(void) {} + \\static void bar(void) {} + , &[_][]const u8{ + \\pub export fn foo() void {} + \\pub fn bar() void {} + }); cases.add_2("parameterless function prototypes", \\void a() {} @@ -84,8 +94,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\void c(); \\void d(void); , &[_][]const u8{ - \\pub fn a(...) void {} - \\pub fn b() void {} + \\pub export fn a() void {} + \\pub export fn b() void {} \\pub extern fn c(...) void; \\pub extern fn d() void; }); @@ -124,7 +134,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\void foo(void) {} \\static void bar(void) {} , &[_][]const u8{ - \\pub fn foo() void {} + \\pub export fn foo() void {} \\pub fn bar() void {} }); @@ -142,7 +152,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} , &[_][]const u8{ \\pub extern fn foo() void; - \\pub fn bar() 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))); \\} @@ -212,7 +222,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ __PRETTY_FUNCTION__; \\} , &[_][]const u8{ - \\pub fn foo() void { + \\pub export fn foo() void { \\ _ = "foo"; \\ _ = "foo"; \\ _ = "void foo(void)"; @@ -229,7 +239,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ a = 1; \\} , &[_][]const u8{ - \\pub fn foo() void { + \\pub export fn foo() void { \\ var a: c_int = undefined; \\ _ = 1; \\ _ = "hey"; @@ -244,7 +254,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ for (int x = 0; x < 10; x++); \\} , &[_][]const u8{ - \\pub fn foo() void { + \\pub export fn foo() void { \\ { \\ var x: c_int = 0; \\ while (x < 10) : (x += 1) {} @@ -257,7 +267,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ do ; while (1); \\} , &[_][]const u8{ // TODO this should be if (1 != 0) break - \\pub fn foo() void { + \\pub export fn foo() void { \\ while (true) { \\ {} \\ if (!1) break; @@ -270,7 +280,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ for (;;); \\} , &[_][]const u8{ - \\pub fn foo() void { + \\pub export fn foo() void { \\ while (true) {} \\} }); @@ -280,7 +290,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ while (1); \\} , &[_][]const u8{ - \\pub fn foo() void { + \\pub export fn foo() void { \\ while (1 != 0) {} \\} }); @@ -326,7 +336,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub extern fn foo() noreturn; }); - cases.addC("simple function", + cases.add("simple function", \\int abs(int a) { \\ return a < 0 ? -a : a; \\} @@ -482,15 +492,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub const THING2 = THING1; }); - cases.add("variables", - \\extern int extern_var; - \\static const int int_var = 13; - , &[_][]const u8{ - \\pub extern var extern_var: c_int; - , - \\pub const int_var: c_int = 13; - }); - cases.add("circular struct definitions", \\struct Bar; \\ @@ -642,7 +643,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub const LUA_GLOBALSINDEX = -10002; }); - cases.addC("post increment", + cases.add("post increment", \\unsigned foo1(unsigned a) { \\ a++; \\ return a; @@ -664,7 +665,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC("shift right assign", + cases.add("shift right assign", \\int log2(unsigned a) { \\ int i = 0; \\ while (a > 0) { @@ -683,7 +684,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC("if statement", + cases.add("if statement", \\int max(int a, int b) { \\ if (a < b) \\ return b; @@ -703,7 +704,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC("==, !=", + cases.add("==, !=", \\int max(int a, int b) { \\ if (a == b) \\ return a; @@ -719,7 +720,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC_both("add, sub, mul, div, rem", + cases.add_both("add, sub, mul, div, rem", \\int s(int a, int b) { \\ int c; \\ c = a + b; @@ -755,7 +756,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC("bitwise binary operators", + cases.add("bitwise binary operators", \\int max(int a, int b) { \\ return (a & b) ^ (a | b); \\} @@ -765,7 +766,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC("logical and, logical or", + cases.add("logical and, logical or", \\int max(int a, int b) { \\ if (a < b || a == b) \\ return b; @@ -781,7 +782,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC("logical and, logical or on none bool values", + cases.add("logical and, logical or on none bool values", \\int and_or_none_bool(int a, float b, void *c) { \\ if (a && b) return 0; \\ if (b && c) return 1; @@ -803,7 +804,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC("assign", + cases.add("assign", \\int max(int a) { \\ int tmp; \\ tmp = a; @@ -818,7 +819,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC("chaining assign", + cases.add("chaining assign", \\void max(int a) { \\ int b, c; \\ c = b = a; @@ -835,7 +836,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC("shift right assign with a fixed size type", + cases.add("shift right assign with a fixed size type", \\#include \\int log2(uint32_t a) { \\ int i = 0; @@ -865,7 +866,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub const Two = 1; }); - cases.addC("function call", + cases.add("function call", \\static void bar(void) { } \\static int baz(void) { return 0; } \\void foo(void) { @@ -883,7 +884,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC("field access expression", + cases.add("field access expression", \\struct Foo { \\ int field; \\}; @@ -899,7 +900,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC("null statements", + cases.add("null statements", \\void foo(void) { \\ ;;;;; \\} @@ -919,7 +920,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub var array: [100]c_int = undefined; }); - cases.addC("array access", + cases.add("array access", \\int array[100]; \\int foo(int index) { \\ return array[index]; @@ -931,7 +932,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC("c style cast", + cases.add("c style cast", \\int float_to_int(float a) { \\ return (int)a; \\} @@ -941,7 +942,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC("void cast", + cases.add("void cast", \\void foo(int a) { \\ (void) a; \\} @@ -951,7 +952,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC("implicit cast to void *", + cases.add("implicit cast to void *", \\void *foo(unsigned short *x) { \\ return x; \\} @@ -961,7 +962,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC("sizeof", + cases.add("sizeof", \\#include \\size_t size_of(void) { \\ return sizeof(int); @@ -972,7 +973,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC("null pointer implicit cast", + cases.add("null pointer implicit cast", \\int* foo(void) { \\ return 0; \\} @@ -982,7 +983,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC("comma operator", + cases.add("comma operator", \\int foo(void) { \\ return 1, 2; \\} @@ -995,7 +996,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC("statement expression", + cases.add("statement expression", \\int foo(void) { \\ return ({ \\ int a = 1; @@ -1011,7 +1012,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC("__extension__ cast", + cases.add("__extension__ cast", \\int foo(void) { \\ return __extension__ 1; \\} @@ -1021,7 +1022,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC("bitshift", + cases.add("bitshift", \\int foo(void) { \\ return (1 << 2) >> 1; \\} @@ -1031,7 +1032,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC("compound assignment operators", + cases.add("compound assignment operators", \\void foo(void) { \\ int a = 0; \\ a += (a += 1); @@ -1089,7 +1090,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC("compound assignment operators unsigned", + cases.add("compound assignment operators unsigned", \\void foo(void) { \\ unsigned a = 0; \\ a += (a += 1); @@ -1147,7 +1148,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC("duplicate typedef", + cases.add("duplicate typedef", \\typedef long foo; \\typedef int bar; \\typedef long foo; @@ -1158,7 +1159,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub const baz = c_int; }); - cases.addC("post increment/decrement", + cases.add("post increment/decrement", \\void foo(void) { \\ int i = 0; \\ unsigned u = 0; @@ -1206,7 +1207,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC("pre increment/decrement", + cases.add("pre increment/decrement", \\void foo(void) { \\ int i = 0; \\ unsigned u = 0; @@ -1250,7 +1251,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC("do loop", + cases.add("do loop", \\void foo(void) { \\ int a = 2; \\ do { @@ -1277,7 +1278,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC("deref function pointer", + cases.add("deref function pointer", \\void foo(void) {} \\int baz(void) { return 0; } \\void bar(void) { @@ -1307,7 +1308,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC("normal deref", + cases.add("normal deref", \\void foo(int *x) { \\ *x = 1; \\} @@ -1338,7 +1339,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ return *ptr; \\} , &[_][]const u8{ - \\pub fn foo() c_int { + \\pub export fn foo() c_int { \\ var x: c_int = 1234; \\ var ptr: [*c]c_int = &x; \\ return ptr.?.*; @@ -1350,7 +1351,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ return "bar"; \\} , &[_][]const u8{ - \\pub fn foo() [*c]const u8 { + \\pub export fn foo() [*c]const u8 { \\ return "bar"; \\} }); @@ -1360,7 +1361,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ return; \\} , &[_][]const u8{ - \\pub fn foo() void { + \\pub export fn foo() void { \\ return; \\} }); @@ -1370,7 +1371,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ for (int i = 0; i < 10; i += 1) { } \\} , &[_][]const u8{ - \\pub fn foo() void { + \\pub export fn foo() void { \\ { \\ var i: c_int = 0; \\ while (i < 10) : (i += 1) {} @@ -1383,7 +1384,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ for (;;) { } \\} , &[_][]const u8{ - \\pub fn foo() void { + \\pub export fn foo() void { \\ while (true) {} \\} }); @@ -1395,7 +1396,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ } \\} , &[_][]const u8{ - \\pub fn foo() void { + \\pub export fn foo() void { \\ while (true) { \\ break; \\ } @@ -1409,7 +1410,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ } \\} , &[_][]const u8{ - \\pub fn foo() void { + \\pub export fn foo() void { \\ while (true) { \\ continue; \\ } @@ -1464,7 +1465,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ return x; \\} , &[_][]const u8{ - \\pub fn foo() c_int { + \\pub export fn foo() c_int { \\ var x: c_int = 1; \\ { \\ var x_0: c_int = 2; @@ -1489,7 +1490,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ return ~x; \\} , &[_][]const u8{ - \\pub fn foo(x: c_int) c_int { + \\pub export fn foo(x: c_int) c_int { \\ return ~x; \\} }); @@ -1502,7 +1503,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ return !c; \\} , &[_][]const u8{ - \\pub fn foo(a: c_int, b: f32, c: ?*c_void) c_int { + \\pub export fn foo(a: c_int, b: f32, c: ?*c_void) c_int { \\ return !(a == 0); \\ return !(a != 0); \\ return !(b != 0); @@ -1515,23 +1516,17 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ return u32; \\} , &[_][]const u8{ - \\pub fn foo(u32_0: c_int) c_int { + \\pub export fn foo(u32_0: c_int) c_int { \\ return u32_0; \\} }); - cases.add("const ptr initializer", - \\static const char *v0 = "0.0.0"; - , &[_][]const u8{ - \\pub var v0: [*c]const u8 = "0.0.0"; - }); - cases.add("static incomplete array inside function", \\void foo(void) { \\ static const char v2[] = "2.2.2"; \\} , &[_][]const u8{ - \\pub fn foo() void { + \\pub export fn foo() void { \\ const v2: [*c]const u8 = "2.2.2"; \\} }); @@ -1560,7 +1555,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ B, \\ C, \\}; - \\pub fn if_none_bool(a: c_int, b: f32, c: ?*c_void, d: enum_SomeEnum) c_int { + \\pub export fn if_none_bool(a: c_int, b: f32, c: ?*c_void, d: enum_SomeEnum) c_int { \\ if (a != 0) return 0; \\ if (b != 0) return 1; \\ if (c != null) return 2; @@ -1577,7 +1572,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ return 3; \\} , &[_][]const u8{ - \\pub fn while_none_bool(a: c_int, b: f32, c: ?*c_void) c_int { + \\pub export fn while_none_bool(a: c_int, b: f32, c: ?*c_void) c_int { \\ while (a != 0) return 0; \\ while (b != 0) return 1; \\ while (c != null) return 2; @@ -1593,7 +1588,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ return 3; \\} , &[_][]const u8{ - \\pub fn for_none_bool(a: c_int, b: f32, c: ?*c_void) c_int { + \\pub export fn for_none_bool(a: c_int, b: f32, c: ?*c_void) c_int { \\ while (a != 0) return 0; \\ while (b != 0) return 1; \\ while (c != null) return 2; @@ -1617,7 +1612,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ } \\} , &[_][]const u8{ - \\pub fn switch_fn(i: c_int) c_int { + \\pub export fn switch_fn(i: c_int) c_int { \\ var res: c_int = 0; \\ __switch: { \\ __case_2: { @@ -1643,7 +1638,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC( + cases.add( "u integer suffix after 0 (zero) in macro definition", "#define ZERO 0U", &[_][]const u8{ @@ -1651,7 +1646,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { }, ); - cases.addC( + cases.add( "l integer suffix after 0 (zero) in macro definition", "#define ZERO 0L", &[_][]const u8{ @@ -1659,7 +1654,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { }, ); - cases.addC( + cases.add( "ul integer suffix after 0 (zero) in macro definition", "#define ZERO 0UL", &[_][]const u8{ @@ -1667,7 +1662,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { }, ); - cases.addC( + cases.add( "lu integer suffix after 0 (zero) in macro definition", "#define ZERO 0LU", &[_][]const u8{ @@ -1675,7 +1670,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { }, ); - cases.addC( + cases.add( "ll integer suffix after 0 (zero) in macro definition", "#define ZERO 0LL", &[_][]const u8{ @@ -1683,7 +1678,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { }, ); - cases.addC( + cases.add( "ull integer suffix after 0 (zero) in macro definition", "#define ZERO 0ULL", &[_][]const u8{ @@ -1691,7 +1686,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { }, ); - cases.addC( + cases.add( "llu integer suffix after 0 (zero) in macro definition", "#define ZERO 0LLU", &[_][]const u8{ @@ -1699,7 +1694,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { }, ); - cases.addC( + cases.add( "bitwise not on u-suffixed 0 (zero) in macro definition", "#define NOT_ZERO (~0U)", &[_][]const u8{ @@ -1707,7 +1702,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { }, ); - cases.addC("implicit casts", + cases.add("implicit casts", \\#include \\ \\void fn_int(int x); @@ -1762,7 +1757,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC("pointer conversion with different alignment", + cases.add("pointer conversion with different alignment", \\void test_ptr_cast() { \\ void *p; \\ { @@ -1796,7 +1791,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC("escape sequences", + cases.add("escape sequences", \\const char *escapes() { \\char a = '\'', \\ b = '\\', @@ -1840,7 +1835,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { } /////////////// Cases for only stage1 because stage2 behavior is better //////////////// - cases.addC("Parameterless function prototypes", + cases.add("Parameterless function prototypes", \\void foo() {} \\void bar(void) {} , &[_][]const u8{ From 48ac84db1b6638d4892a5b9d88d193562e1a4f04 Mon Sep 17 00:00:00 2001 From: Vexu Date: Thu, 12 Dec 2019 20:35:40 +0200 Subject: [PATCH 4/8] translate-c-2 translate apvalue --- src-self-hosted/clang.zig | 10 ++- src-self-hosted/translate_c.zig | 152 ++++++++++++++++++++++++++++---- 2 files changed, 142 insertions(+), 20 deletions(-) diff --git a/src-self-hosted/clang.zig b/src-self-hosted/clang.zig index 3b498ffdab..5b7605c021 100644 --- a/src-self-hosted/clang.zig +++ b/src-self-hosted/clang.zig @@ -1,5 +1,6 @@ const builtin = @import("builtin"); +pub const struct_ZigClangAPInt = @OpaqueType(); pub const struct_ZigClangAPSInt = @OpaqueType(); pub const struct_ZigClangAPFloat = @OpaqueType(); pub const struct_ZigClangASTContext = @OpaqueType(); @@ -747,6 +748,7 @@ pub extern fn ZigClangType_getTypeClass(self: ?*const struct_ZigClangType) ZigCl pub extern fn ZigClangType_getPointeeType(self: ?*const struct_ZigClangType) struct_ZigClangQualType; pub extern fn ZigClangType_isVoidType(self: ?*const struct_ZigClangType) bool; pub extern fn ZigClangType_getTypeClassName(self: *const struct_ZigClangType) [*:0]const u8; +pub extern fn ZigClangType_getAsArrayTypeUnsafe(self: *const ZigClangType) *const ZigClangArrayType; pub extern fn ZigClangStmt_getBeginLoc(self: *const struct_ZigClangStmt) struct_ZigClangSourceLocation; pub extern fn ZigClangStmt_getStmtClass(self: ?*const struct_ZigClangStmt) ZigClangStmtClass; pub extern fn ZigClangStmt_classof_Expr(self: ?*const struct_ZigClangStmt) bool; @@ -756,8 +758,8 @@ pub extern fn ZigClangExpr_getBeginLoc(self: *const struct_ZigClangExpr) struct_ 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_getArrayInitializedElts(self: ?*const struct_ZigClangAPValue) c_uint; -pub extern fn ZigClangAPValue_getArrayInitializedElt(self: ?*const struct_ZigClangAPValue, i: c_uint) ?*const struct_ZigClangAPValue; -pub extern fn ZigClangAPValue_getArrayFiller(self: ?*const struct_ZigClangAPValue) ?*const struct_ZigClangAPValue; +pub extern fn ZigClangAPValue_getArrayInitializedElt(self: ?*const struct_ZigClangAPValue, i: c_uint) *const struct_ZigClangAPValue; +pub extern fn ZigClangAPValue_getArrayFiller(self: ?*const struct_ZigClangAPValue) *const struct_ZigClangAPValue; 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; @@ -766,6 +768,8 @@ pub extern fn ZigClangAPSInt_negate(self: ?*const struct_ZigClangAPSInt) ?*const pub extern fn ZigClangAPSInt_free(self: ?*const struct_ZigClangAPSInt) void; pub extern fn ZigClangAPSInt_getRawData(self: ?*const struct_ZigClangAPSInt) [*c]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; pub extern fn ZigClangASTUnit_delete(self: ?*struct_ZigClangASTUnit) void; @@ -935,6 +939,8 @@ pub extern fn ZigClangImplicitCastExpr_getSubExpr(*const ZigClangImplicitCastExp pub extern fn ZigClangArrayType_getElementType(*const ZigClangArrayType) ZigClangQualType; +pub extern fn ZigClangConstantArrayType_getElementType(self: *const struct_ZigClangConstantArrayType) ZigClangQualType; +pub extern fn ZigClangConstantArrayType_getSize(self: *const struct_ZigClangConstantArrayType) *const struct_ZigClangAPInt; pub extern fn ZigClangDeclRefExpr_getDecl(*const ZigClangDeclRefExpr) *const ZigClangValueDecl; pub extern fn ZigClangParenType_getInnerType(*const ZigClangParenType) ZigClangQualType; diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index a29755aaba..db3e1c5e41 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -322,7 +322,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { var var_node = try transCreateNodeVarDecl(c, true, is_extern, is_const, var_name); - _= try appendToken(rp.c, .Colon, ":"); + _ = try appendToken(rp.c, .Colon, ":"); var_node.type_node = transQualType(rp, qual_type, var_decl_loc) catch |err| switch (err) { error.UnsupportedType => { return failDecl(c, var_decl_loc, var_name, "unable to resolve variable type", .{}); @@ -634,15 +634,8 @@ fn transDeclStmt(rp: RestorePoint, parent_scope: *Scope, stmt: *const ZigClangDe const eq_token = try appendToken(c, .Equal, "="); const init_node = if (ZigClangVarDecl_getInit(var_decl)) |expr| (try transExpr(rp, scope, expr, .used, .r_value)).node - else blk: { - const undefined_token = try appendToken(c, .Keyword_undefined, "undefined"); - const undefined_node = try rp.c.a().create(ast.Node.UndefinedLiteral); - undefined_node.* = ast.Node.UndefinedLiteral{ - .base = ast.Node{ .id = .UndefinedLiteral }, - .token = undefined_token, - }; - break :blk &undefined_node.base; - }; + else + try transCreateNodeUndefinedLiteral(rp.c); const semicolon_token = try appendToken(c, .Semicolon, ";"); const node = try c.a().create(ast.Node.VarDecl); @@ -1288,6 +1281,20 @@ fn transCreateNodeUndefinedLiteral(c: *Context) !*ast.Node { return &node.base; } +fn transCreateNodeArrayInitializer(c: *Context, type_node: *ast.Node) !*ast.Node.SuffixOp { + _ = try appendToken(c, .LBrace, "{"); + const node = try c.a().create(ast.Node.SuffixOp); + node.* = ast.Node.SuffixOp{ + .base = ast.Node{ .id = .SuffixOp }, + .lhs = .{ .node = type_node }, + .op = .{ + .ArrayInitializer = ast.Node.SuffixOp.Op.InitList.init(c.a()), + }, + .rtoken = undefined, // set after appending values + }; + return node; +} + fn transCreateNodeVarDecl( c: *Context, is_pub: bool, @@ -1333,6 +1340,16 @@ fn transCreateNodeVarDecl( return node; } +fn transCreateNodeInt(c: *Context, int: var) !*ast.Node { + const token = try appendToken(c, .IntegerLiteral, try std.fmt.allocPrint(c.a(), "{}", .{int})); + const node = try c.a().create(ast.Node.IntegerLiteral); + node.* = ast.Node.IntegerLiteral{ + .base = ast.Node{ .id = .IntegerLiteral }, + .token = token, + }; + return &node.base; +} + const RestorePoint = struct { c: *Context, token_index: ast.TokenIndex, @@ -1416,6 +1433,27 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour pointer_node.rhs = try transQualType(rp, child_qt, source_loc); return &pointer_node.base; }, + .ConstantArray => { + const const_arr_ty = @ptrCast(*const ZigClangConstantArrayType, ty); + + const size_ap_int = ZigClangConstantArrayType_getSize(const_arr_ty); + const size = ZigClangAPInt_getLimitedValue(size_ap_int, std.math.maxInt(usize)); + var node = try transCreateNodePrefixOp( + rp.c, + .{ + .ArrayType = .{ + .len_expr = undefined, + .sentinel = null, + }, + }, + .LBracket, + "[", + ); + node.op.ArrayType.len_expr = try transCreateNodeInt(rp.c, size); + _ = try appendToken(rp.c, .RBracket, "]"); + node.rhs = try transQualType(rp, ZigClangConstantArrayType_getElementType(const_arr_ty), source_loc); + return &node.base; + }, else => { const type_name = rp.c.str(ZigClangType_getTypeClassName(ty)); return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported type: '{}'", .{type_name}); @@ -1423,14 +1461,92 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour } } -fn transApValue(rp: RestorePoint, ap_value: *const ZigClangAPValue, qual_type: ZigClangQualType, source_loc: ZigClangSourceLocation) TransError!*ast.Node { - return revertAndWarn( - rp, - error.UnsupportedTranslation, - source_loc, - "TODO implement translation of ap value", - .{}, - ); +fn transApValue(rp: RestorePoint, ap_value: *const ZigClangAPValue, qt: ZigClangQualType, source_loc: ZigClangSourceLocation) TransError!*ast.Node { + switch (ZigClangAPValue_getKind(ap_value)) { + .None => return transCreateNodeUndefinedLiteral(rp.c), + .Int => return transCreateNodeAPInt(rp.c, ZigClangAPValue_getInt(ap_value)), + .Array => { + // TODO evaluateValue is null for Array init for some reason + // TODO use anon literals once they work properly + const init_count = ZigClangAPValue_getArrayInitializedElts(ap_value); + const all_count = ZigClangAPValue_getArraySize(ap_value); + const leftover_count = all_count - init_count; + const qt_type = ZigClangQualType_getTypePtr(qt); + const child_qt = ZigClangArrayType_getElementType(ZigClangType_getAsArrayTypeUnsafe(qt_type)); + + var init_node: *ast.Node.SuffixOp = undefined; + var cat_tok: ast.TokenIndex = undefined; + if (init_count != 0) { + var type_node = try transQualType(rp, qt, source_loc); + init_node = try transCreateNodeArrayInitializer(rp.c, type_node); + var i: c_uint = 0; + while (i < init_count) : (i += 1) { + const elem_ap_val = ZigClangAPValue_getArrayInitializedElt(ap_value, i); + try init_node.op.ArrayInitializer.push(try transApValue(rp, elem_ap_val, child_qt, source_loc)); + _ = try appendToken(rp.c, .Comma, ","); + } + init_node.rtoken = try appendToken(rp.c, .RBrace, "}"); + if (leftover_count == 0) { + return &init_node.base; + } + cat_tok = try appendToken(rp.c, .PlusPlus, "++"); + } + + var filler_type_node = try transQualType(rp, qt, source_loc); + var filler_init_node = try transCreateNodeArrayInitializer(rp.c, filler_type_node); + const filler_ap_val = ZigClangAPValue_getArrayFiller(ap_value); + try filler_init_node.op.ArrayInitializer.push(try transApValue(rp, filler_ap_val, child_qt, source_loc)); + filler_init_node.rtoken = try appendToken(rp.c, .RBrace, "}"); + + const rhs_node = if (leftover_count == 1) + &filler_init_node.base + else blk: { + const mul_tok = try appendToken(rp.c, .AsteriskAsterisk, "**"); + const mul_node = try rp.c.a().create(ast.Node.InfixOp); + mul_node.* = .{ + .base = .{ .id = .InfixOp }, + .op_token = mul_tok, + .lhs = &filler_init_node.base, + .op = .ArrayMult, + .rhs = try transCreateNodeInt(rp.c, leftover_count), + }; + break :blk &mul_node.base; + }; + + if (init_count == 0) { + return rhs_node; + } + + const cat_node = try rp.c.a().create(ast.Node.InfixOp); + cat_node.* = .{ + .base = .{ .id = .InfixOp }, + .op_token = cat_tok, + .lhs = &init_node.base, + .op = .ArrayCat, + .rhs = rhs_node, + }; + return &cat_node.base; + }, + .LValue => { + const lval_base = ZigClangAPValue_getLValueBase(ap_value); + const expr = ZigClangAPValueLValueBase_dyn_cast_Expr(lval_base); + if (expr) |e| { + return (try transExpr(rp, &rp.c.global_scope.base, e, .used, .r_value)).node; + } + try emitWarning(rp.c, source_loc, "TODO handle initializer LValue ValueDecl", .{}); + }, + .Float => try emitWarning(rp.c, source_loc, "unsupported initializer value kind: Float", .{}), + .ComplexInt => try emitWarning(rp.c, source_loc, "unsupported initializer value kind: ComplexInt", .{}), + .ComplexFloat => try emitWarning(rp.c, source_loc, "Tunsupported initializer value kind: ComplexFloat", .{}), + .Vector => try emitWarning(rp.c, source_loc, "unsupported initializer value kind: Vector", .{}), + .Struct => try emitWarning(rp.c, source_loc, "unsupported initializer value kind: Struct", .{}), + .Union => try emitWarning(rp.c, source_loc, "unsupported initializer value kind: Union", .{}), + .MemberPointer => try emitWarning(rp.c, source_loc, "unsupported initializer value kind: MemberPointer", .{}), + .AddrLabelDiff => try emitWarning(rp.c, source_loc, "unsupported initializer value kind: AddrLabelDiff", .{}), + .Indeterminate => try emitWarning(rp.c, source_loc, "unsupported initializer value kind: Indeterminate", .{}), + .FixedPoint => try emitWarning(rp.c, source_loc, "unsupported initializer value kind: FixedPoint", .{}), + } + return error.UnsupportedTranslation; } const FnDeclContext = struct { From 0795f17db23fff5aada41008348a63cbc9e0321b Mon Sep 17 00:00:00 2001 From: Vexu Date: Thu, 12 Dec 2019 21:14:55 +0200 Subject: [PATCH 5/8] translate-c-2 incompleteArray --- src-self-hosted/clang.zig | 2 ++ src-self-hosted/translate_c.zig | 15 +++++++++- test/translate_c.zig | 50 ++++++++++----------------------- 3 files changed, 31 insertions(+), 36 deletions(-) diff --git a/src-self-hosted/clang.zig b/src-self-hosted/clang.zig index 5b7605c021..eea6d757dc 100644 --- a/src-self-hosted/clang.zig +++ b/src-self-hosted/clang.zig @@ -938,6 +938,7 @@ pub extern fn ZigClangImplicitCastExpr_getCastKind(*const ZigClangImplicitCastEx pub extern fn ZigClangImplicitCastExpr_getSubExpr(*const ZigClangImplicitCastExpr) *const ZigClangExpr; pub extern fn ZigClangArrayType_getElementType(*const ZigClangArrayType) ZigClangQualType; +pub extern fn ZigClangIncompleteArrayType_getElementType(*const ZigClangIncompleteArrayType) ZigClangQualType; pub extern fn ZigClangConstantArrayType_getElementType(self: *const struct_ZigClangConstantArrayType) ZigClangQualType; pub extern fn ZigClangConstantArrayType_getSize(self: *const struct_ZigClangConstantArrayType) *const struct_ZigClangAPInt; @@ -968,6 +969,7 @@ pub const struct_ZigClangAPValue = extern struct { Kind: ZigClangAPValueKind, Data: if (builtin.os == .windows and builtin.abi == .msvc) [52]u8 else [68]u8, }; +pub extern fn ZigClangVarDecl_getTypeSourceInfo_getType(self: *const struct_ZigClangVarDecl) struct_ZigClangQualType; pub extern fn ZigClangIntegerLiteral_EvaluateAsInt(*const ZigClangIntegerLiteral, *ZigClangExprEvalResult, *const ZigClangASTContext) bool; pub extern fn ZigClangIntegerLiteral_getBeginLoc(*const ZigClangIntegerLiteral) ZigClangSourceLocation; diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index db3e1c5e41..80d0e21989 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -609,7 +609,7 @@ fn transDeclStmt(rp: RestorePoint, parent_scope: *Scope, stmt: *const ZigClangDe null else try appendToken(c, .Keyword_threadlocal, "threadlocal"); - const qual_type = ZigClangVarDecl_getType(var_decl); + const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl); const mut_token = if (ZigClangQualType_isConstQualified(qual_type)) try appendToken(c, .Keyword_const, "const") else @@ -1454,6 +1454,19 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour node.rhs = try transQualType(rp, ZigClangConstantArrayType_getElementType(const_arr_ty), source_loc); return &node.base; }, + .IncompleteArray => { + const incomplete_array_ty = @ptrCast(*const ZigClangIncompleteArrayType, ty); + + const child_qt = ZigClangIncompleteArrayType_getElementType(incomplete_array_ty); + var node = try transCreateNodePtrType( + rp.c, + ZigClangQualType_isConstQualified(child_qt), + ZigClangQualType_isVolatileQualified(child_qt), + .Identifier, + ); + node.rhs = try transQualType(rp, child_qt, source_loc); + return &node.base; + }, else => { const type_name = rp.c.str(ZigClangType_getTypeClassName(ty)); return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported type: '{}'", .{type_name}); diff --git a/test/translate_c.zig b/test/translate_c.zig index 5772763a65..3b067d1bea 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -1,11 +1,11 @@ const tests = @import("tests.zig"); const builtin = @import("builtin"); -// add_both - test for stage1 and stage2, in #include mode -// add - test stage1 only, in #include mode -// add_2 - test stage2 only, in #include mode +// add_both - test for stage1 and stage2 +// add - test stage1 only +// add_2 - test stage2 only -pub export fn addCases(cases: *tests.TranslateCContext) void { +pub fn addCases(cases: *tests.TranslateCContext) void { /////////////// Cases that pass for both stage1/stage2 //////////////// cases.add_both("simple function prototypes", \\void __attribute__((noreturn)) foo(void); @@ -66,21 +66,17 @@ pub export fn addCases(cases: *tests.TranslateCContext) void { \\pub var v0: [*c]const u8 = "0.0.0"; }); - /////////////// Cases that pass for only stage2 //////////////// - - cases.add_2("Parameterless function prototypes", - \\void a() {} - \\void b(void) {} - \\void c(); - \\void d(void); + cases.add_both("static incomplete array inside function", + \\void foo(void) { + \\ static const char v2[] = "2.2.2"; + \\} , &[_][]const u8{ - \\pub export fn a() void {} - \\pub export fn b() void {} - \\pub extern fn c(...) void; - \\pub extern fn d() void; + \\pub export fn foo() void { + \\ const v2: [*c]const u8 = "2.2.2"; + \\} }); - cases.add_2("simple function definition", + cases.add_both("simple function definition", \\void foo(void) {} \\static void bar(void) {} , &[_][]const u8{ @@ -88,7 +84,9 @@ pub export fn addCases(cases: *tests.TranslateCContext) void { \\pub fn bar() void {} }); - cases.add_2("parameterless function prototypes", + /////////////// Cases that pass for only stage2 //////////////// + + cases.add_2("Parameterless function prototypes", \\void a() {} \\void b(void) {} \\void c(); @@ -130,14 +128,6 @@ pub export fn addCases(cases: *tests.TranslateCContext) void { \\}; }); - cases.add_both("simple function definition", - \\void foo(void) {} - \\static void bar(void) {} - , &[_][]const u8{ - \\pub export fn foo() void {} - \\pub fn bar() void {} - }); - cases.add("macro with left shift", \\#define REDISMODULE_READ (1<<0) , &[_][]const u8{ @@ -1521,16 +1511,6 @@ pub export fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add("static incomplete array inside function", - \\void foo(void) { - \\ static const char v2[] = "2.2.2"; - \\} - , &[_][]const u8{ - \\pub export fn foo() void { - \\ const v2: [*c]const u8 = "2.2.2"; - \\} - }); - cases.add("macro pointer cast", \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE) , &[_][]const u8{ From eb057ef41c8a5482586fc39bab11c280e261ea94 Mon Sep 17 00:00:00 2001 From: Vexu Date: Fri, 13 Dec 2019 14:55:36 +0200 Subject: [PATCH 6/8] translate-c-2 dont eval init expr --- src-self-hosted/clang.zig | 11 +- src-self-hosted/translate_c.zig | 299 +++++++++++++++----------------- src/zig_clang.cpp | 22 +++ src/zig_clang.h | 6 + test/translate_c.zig | 10 ++ 5 files changed, 183 insertions(+), 165 deletions(-) diff --git a/src-self-hosted/clang.zig b/src-self-hosted/clang.zig index eea6d757dc..2ed011cc1e 100644 --- a/src-self-hosted/clang.zig +++ b/src-self-hosted/clang.zig @@ -74,6 +74,7 @@ pub const struct_ZigClangVarDecl = @OpaqueType(); pub const struct_ZigClangWhileStmt = @OpaqueType(); pub const struct_ZigClangFunctionType = @OpaqueType(); pub const struct_ZigClangPredefinedExpr = @OpaqueType(); +pub const struct_ZigClangInitListExpr = @OpaqueType(); pub const ZigClangBO = extern enum { PtrMemD, @@ -755,11 +756,12 @@ pub extern fn ZigClangStmt_classof_Expr(self: ?*const struct_ZigClangStmt) bool; pub extern fn ZigClangExpr_getStmtClass(self: ?*const struct_ZigClangExpr) ZigClangStmtClass; pub extern fn ZigClangExpr_getType(self: ?*const struct_ZigClangExpr) struct_ZigClangQualType; pub extern fn ZigClangExpr_getBeginLoc(self: *const struct_ZigClangExpr) struct_ZigClangSourceLocation; +pub extern fn ZigClangInitListExpr_getInit(self: ?*const struct_ZigClangInitListExpr, i: c_uint) *const ZigClangExpr; +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_getArrayInitializedElts(self: ?*const struct_ZigClangAPValue) c_uint; -pub extern fn ZigClangAPValue_getArrayInitializedElt(self: ?*const struct_ZigClangAPValue, i: c_uint) *const struct_ZigClangAPValue; -pub extern fn ZigClangAPValue_getArrayFiller(self: ?*const struct_ZigClangAPValue) *const struct_ZigClangAPValue; 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; @@ -867,6 +869,7 @@ pub const ZigClangVarDecl = struct_ZigClangVarDecl; pub const ZigClangWhileStmt = struct_ZigClangWhileStmt; pub const ZigClangFunctionType = struct_ZigClangFunctionType; pub const ZigClangPredefinedExpr = struct_ZigClangPredefinedExpr; +pub const ZigClangInitListExpr = struct_ZigClangInitListExpr; pub const struct_ZigClangSourceLocation = extern struct { ID: c_uint, @@ -921,9 +924,8 @@ pub extern fn ZigClangDeclStmt_decl_begin(self: *const ZigClangDeclStmt) ZigClan pub extern fn ZigClangDeclStmt_decl_end(self: *const ZigClangDeclStmt) ZigClangDeclStmt_const_decl_iterator; pub extern fn ZigClangVarDecl_getLocation(self: *const struct_ZigClangVarDecl) ZigClangSourceLocation; -pub extern fn ZigClangVarDecl_hasExternalStorage(self: *const struct_ZigClangVarDecl) bool; -pub extern fn ZigClangVarDecl_isFileVarDecl(self: *const struct_ZigClangVarDecl) bool; pub extern fn ZigClangVarDecl_hasInit(self: *const struct_ZigClangVarDecl) bool; +pub extern fn ZigClangVarDecl_getStorageClass(self: *const ZigClangVarDecl) ZigClangStorageClass; pub extern fn ZigClangVarDecl_getType(self: ?*const struct_ZigClangVarDecl) struct_ZigClangQualType; pub extern fn ZigClangVarDecl_getInit(*const ZigClangVarDecl) ?*const ZigClangExpr; pub extern fn ZigClangVarDecl_getTLSKind(self: ?*const struct_ZigClangVarDecl) ZigClangVarDecl_TLSKind; @@ -964,7 +966,6 @@ pub const struct_ZigClangExprEvalResult = extern struct { Val: ZigClangAPValue, }; -pub extern fn ZigClangVarDecl_evaluateValue(self: *const struct_ZigClangVarDecl) ?*const ZigClangAPValue; pub const struct_ZigClangAPValue = extern struct { Kind: ZigClangAPValueKind, Data: if (builtin.os == .windows and builtin.abi == .msvc) [52]u8 else [68]u8, diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index 80d0e21989..a4874d92e3 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -305,54 +305,83 @@ 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 const rp = makeRestorePoint(c); + const visib_tok = try appendToken(c, .Keyword_pub, "pub"); + + const thread_local_token = if (ZigClangVarDecl_getTLSKind(var_decl) == .None) + null + else + try appendToken(c, .Keyword_threadlocal, "threadlocal"); + var scope = &c.global_scope.base; const var_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, var_decl))); const var_decl_loc = ZigClangVarDecl_getLocation(var_decl); - switch (ZigClangVarDecl_getTLSKind(var_decl)) { - .None => {}, - .Static => return failDecl(c, var_decl_loc, var_name, "static thread local storage not supported", .{}), - .Dynamic => return failDecl(c, var_decl_loc, var_name, "dynamic thread local storag not supported", .{}), - } - - const qual_type = ZigClangVarDecl_getType(var_decl); - const is_extern = ZigClangVarDecl_hasExternalStorage(var_decl); - const is_static = ZigClangVarDecl_isFileVarDecl(var_decl); + const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl); + const storage_class = ZigClangVarDecl_getStorageClass(var_decl); const is_const = ZigClangQualType_isConstQualified(qual_type); - var var_node = try transCreateNodeVarDecl(c, true, is_extern, is_const, var_name); + const extern_tok = if (storage_class == .Extern) + try appendToken(c, .Keyword_extern, "extern") + else if (storage_class != .Static) + try appendToken(c, .Keyword_export, "export") + else + null; - _ = try appendToken(rp.c, .Colon, ":"); - var_node.type_node = transQualType(rp, qual_type, var_decl_loc) catch |err| switch (err) { + const mut_tok = if (is_const) + try appendToken(c, .Keyword_const, "const") + else + try appendToken(c, .Keyword_var, "var"); + + const name_tok = try appendToken(c, .Identifier, var_name); + + _ = try appendToken(c, .Colon, ":"); + const type_node = transQualType(rp, qual_type, var_decl_loc) catch |err| switch (err) { error.UnsupportedType => { return failDecl(c, var_decl_loc, var_name, "unable to resolve variable type", .{}); }, error.OutOfMemory => |e| return e, }; - if (is_static and !is_extern) { - const eq_tok = try appendToken(c, .Equal, "="); - const init_node = if (ZigClangVarDecl_hasInit(var_decl)) blk: { - const ap_value = ZigClangVarDecl_evaluateValue(var_decl) orelse - return failDecl(c, var_decl_loc, var_name, "unable to evaluate initializer", .{}); - break :blk transApValue(rp, ap_value, qual_type, var_decl_loc) catch |err| switch (err) { + var eq_tok: ast.TokenIndex = undefined; + var init_node: ?*ast.Node = null; + + if (ZigClangVarDecl_hasInit(var_decl)) { + eq_tok = try appendToken(c, .Equal, "="); + init_node = if (ZigClangVarDecl_getInit(var_decl)) |expr| blk: { + var res = transExpr(rp, &c.global_scope.base, expr, .used, .r_value) catch |err| switch (err) { error.UnsupportedTranslation, error.UnsupportedType, => { - return failDecl(c, var_decl_loc, var_name, "unable to evaluate initializer", .{}); + return failDecl(c, var_decl_loc, var_name, "unable to translate initializer", .{}); }, error.OutOfMemory => |e| return e, }; + break :blk res.node; } else try transCreateNodeUndefinedLiteral(c); - var_node.eq_token = eq_tok; - var_node.init_node = init_node; - } else if (!is_extern) { - return failDecl(c, var_decl_loc, var_name, "non-extern, non-static variable not supported", .{}); + } else if (storage_class != .Extern) { + return failDecl(c, var_decl_loc, var_name, "non-extern variable has no initializer", .{}); } - var_node.semicolon_token = try appendToken(rp.c, .Semicolon, ";"); - return addTopLevelDecl(c, var_name, &var_node.base); + 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 = thread_local_token, + .name_token = name_tok, + .eq_token = eq_tok, + .mut_token = mut_tok, + .comptime_token = null, + .extern_export_token = extern_tok, + .lib_name = null, + .type_node = type_node, + .align_node = null, + .section_node = null, + .init_node = init_node, + .semicolon_token = try appendToken(c, .Semicolon, ";"), + }; + return addTopLevelDecl(c, var_name, &node.base); } const ResultUsed = enum { @@ -384,6 +413,7 @@ fn transStmt( .ReturnStmtClass => return transReturnStmt(rp, scope, @ptrCast(*const ZigClangReturnStmt, stmt)), .StringLiteralClass => return transStringLiteral(rp, scope, @ptrCast(*const ZigClangStringLiteral, stmt), result_used), .ParenExprClass => return transExpr(rp, scope, ZigClangParenExpr_getSubExpr(@ptrCast(*const ZigClangParenExpr, stmt)), result_used, lrvalue), + .InitListExprClass => return transInitListExpr(rp, scope, @ptrCast(*const ZigClangInitListExpr, stmt), result_used), else => { return revertAndWarn( rp, @@ -635,7 +665,7 @@ fn transDeclStmt(rp: RestorePoint, parent_scope: *Scope, stmt: *const ZigClangDe const init_node = if (ZigClangVarDecl_getInit(var_decl)) |expr| (try transExpr(rp, scope, expr, .used, .r_value)).node else - try transCreateNodeUndefinedLiteral(rp.c); + try transCreateNodeUndefinedLiteral(c); const semicolon_token = try appendToken(c, .Semicolon, ";"); const node = try c.a().create(ast.Node.VarDecl); @@ -725,7 +755,7 @@ fn transImplicitCastExpr( .FunctionToPointerDecay, .ArrayToPointerDecay => { return maybeSuppressResult(rp, scope, result_used, sub_expr_node); }, - .LValueToRValue => { + .LValueToRValue, .NoOp => { return transExpr(rp, scope, sub_expr, .used, .r_value); }, else => |kind| return revertAndWarn( @@ -906,6 +936,88 @@ fn transExpr( return transStmt(rp, scope, @ptrCast(*const ZigClangStmt, expr), used, lrvalue); } +fn transInitListExpr( + rp: RestorePoint, + scope: *Scope, + expr: *const ZigClangInitListExpr, + used: ResultUsed, +) TransError!TransResult { + // TODO use anon literals once they work properly + const qt = getExprQualType(rp.c, @ptrCast(*const ZigClangExpr, expr)); + const qual_type = ZigClangQualType_getTypePtr(qt); + const source_loc = ZigClangExpr_getBeginLoc(@ptrCast(*const ZigClangExpr, expr)); + const arr_type = ZigClangType_getAsArrayTypeUnsafe(qual_type); + const child_qt = ZigClangArrayType_getElementType(arr_type); + const init_count = ZigClangInitListExpr_getNumInits(expr); + const all_count = 200; //ZigClangArrayType_getSize(arr_type); + const leftover_count = all_count - init_count; + + var init_node: *ast.Node.SuffixOp = undefined; + var cat_tok: ast.TokenIndex = undefined; + if (init_count != 0) { + var type_node = try transQualType(rp, qt, source_loc); + init_node = try transCreateNodeArrayInitializer(rp.c, type_node); + var i: c_uint = 0; + while (i < init_count) : (i += 1) { + const elem_expr = ZigClangInitListExpr_getInit(expr, i); + try init_node.op.ArrayInitializer.push((try transExpr(rp, scope, elem_expr, .used, .r_value)).node); + _ = try appendToken(rp.c, .Comma, ","); + } + init_node.rtoken = try appendToken(rp.c, .RBrace, "}"); + if (leftover_count == 0) { + return TransResult{ + .node = &init_node.base, + .child_scope = scope, + .node_scope = scope, + }; + } + cat_tok = try appendToken(rp.c, .PlusPlus, "++"); + } + + var filler_type_node = try transQualType(rp, qt, source_loc); + var filler_init_node = try transCreateNodeArrayInitializer(rp.c, filler_type_node); + const filler_val_expr = ZigClangInitListExpr_getArrayFiller(expr); + try filler_init_node.op.ArrayInitializer.push((try transExpr(rp, scope, filler_val_expr, .used, .r_value)).node); + filler_init_node.rtoken = try appendToken(rp.c, .RBrace, "}"); + + const rhs_node = if (leftover_count == 1) + &filler_init_node.base + else blk: { + const mul_tok = try appendToken(rp.c, .AsteriskAsterisk, "**"); + const mul_node = try rp.c.a().create(ast.Node.InfixOp); + mul_node.* = .{ + .base = .{ .id = .InfixOp }, + .op_token = mul_tok, + .lhs = &filler_init_node.base, + .op = .ArrayMult, + .rhs = try transCreateNodeInt(rp.c, leftover_count), + }; + break :blk &mul_node.base; + }; + + if (init_count == 0) { + return TransResult{ + .node = rhs_node, + .child_scope = scope, + .node_scope = scope, + }; + } + + const cat_node = try rp.c.a().create(ast.Node.InfixOp); + cat_node.* = .{ + .base = .{ .id = .InfixOp }, + .op_token = cat_tok, + .lhs = &init_node.base, + .op = .ArrayCat, + .rhs = rhs_node, + }; + return TransResult{ + .node = &cat_node.base, + .child_scope = scope, + .node_scope = scope, + }; +} + fn findBlockScope(inner: *Scope) *Scope.Block { var scope = inner; while (true) : (scope = scope.parent orelse unreachable) { @@ -1295,51 +1407,6 @@ fn transCreateNodeArrayInitializer(c: *Context, type_node: *ast.Node) !*ast.Node return node; } -fn transCreateNodeVarDecl( - c: *Context, - is_pub: bool, - is_extern: bool, - is_const: bool, - var_name: []const u8, -) !*ast.Node.VarDecl { - const visb_tok = if (is_pub) - try appendToken(c, .Keyword_pub, "pub") - else - null; - - const extern_tok = if (is_extern) - try appendToken(c, .Keyword_extern, "extern") - else - null; - - const mut_tok = if (is_const) - try appendToken(c, .Keyword_const, "const") - else - try appendToken(c, .Keyword_var, "var"); - - const name_tok = try appendToken(c, .Identifier, var_name); - - const node = try c.a().create(ast.Node.VarDecl); - node.* = ast.Node.VarDecl{ - .base = ast.Node{ .id = .VarDecl }, - .doc_comments = null, - .visib_token = visb_tok, - .thread_local_token = null, - .name_token = name_tok, - .eq_token = undefined, // set by caller - .mut_token = mut_tok, - .comptime_token = null, - .extern_export_token = extern_tok, - .lib_name = null, - .type_node = null, - .align_node = null, - .section_node = null, - .init_node = null, - .semicolon_token = undefined, // set by caller - }; - return node; -} - fn transCreateNodeInt(c: *Context, int: var) !*ast.Node { const token = try appendToken(c, .IntegerLiteral, try std.fmt.allocPrint(c.a(), "{}", .{int})); const node = try c.a().create(ast.Node.IntegerLiteral); @@ -1474,94 +1541,6 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour } } -fn transApValue(rp: RestorePoint, ap_value: *const ZigClangAPValue, qt: ZigClangQualType, source_loc: ZigClangSourceLocation) TransError!*ast.Node { - switch (ZigClangAPValue_getKind(ap_value)) { - .None => return transCreateNodeUndefinedLiteral(rp.c), - .Int => return transCreateNodeAPInt(rp.c, ZigClangAPValue_getInt(ap_value)), - .Array => { - // TODO evaluateValue is null for Array init for some reason - // TODO use anon literals once they work properly - const init_count = ZigClangAPValue_getArrayInitializedElts(ap_value); - const all_count = ZigClangAPValue_getArraySize(ap_value); - const leftover_count = all_count - init_count; - const qt_type = ZigClangQualType_getTypePtr(qt); - const child_qt = ZigClangArrayType_getElementType(ZigClangType_getAsArrayTypeUnsafe(qt_type)); - - var init_node: *ast.Node.SuffixOp = undefined; - var cat_tok: ast.TokenIndex = undefined; - if (init_count != 0) { - var type_node = try transQualType(rp, qt, source_loc); - init_node = try transCreateNodeArrayInitializer(rp.c, type_node); - var i: c_uint = 0; - while (i < init_count) : (i += 1) { - const elem_ap_val = ZigClangAPValue_getArrayInitializedElt(ap_value, i); - try init_node.op.ArrayInitializer.push(try transApValue(rp, elem_ap_val, child_qt, source_loc)); - _ = try appendToken(rp.c, .Comma, ","); - } - init_node.rtoken = try appendToken(rp.c, .RBrace, "}"); - if (leftover_count == 0) { - return &init_node.base; - } - cat_tok = try appendToken(rp.c, .PlusPlus, "++"); - } - - var filler_type_node = try transQualType(rp, qt, source_loc); - var filler_init_node = try transCreateNodeArrayInitializer(rp.c, filler_type_node); - const filler_ap_val = ZigClangAPValue_getArrayFiller(ap_value); - try filler_init_node.op.ArrayInitializer.push(try transApValue(rp, filler_ap_val, child_qt, source_loc)); - filler_init_node.rtoken = try appendToken(rp.c, .RBrace, "}"); - - const rhs_node = if (leftover_count == 1) - &filler_init_node.base - else blk: { - const mul_tok = try appendToken(rp.c, .AsteriskAsterisk, "**"); - const mul_node = try rp.c.a().create(ast.Node.InfixOp); - mul_node.* = .{ - .base = .{ .id = .InfixOp }, - .op_token = mul_tok, - .lhs = &filler_init_node.base, - .op = .ArrayMult, - .rhs = try transCreateNodeInt(rp.c, leftover_count), - }; - break :blk &mul_node.base; - }; - - if (init_count == 0) { - return rhs_node; - } - - const cat_node = try rp.c.a().create(ast.Node.InfixOp); - cat_node.* = .{ - .base = .{ .id = .InfixOp }, - .op_token = cat_tok, - .lhs = &init_node.base, - .op = .ArrayCat, - .rhs = rhs_node, - }; - return &cat_node.base; - }, - .LValue => { - const lval_base = ZigClangAPValue_getLValueBase(ap_value); - const expr = ZigClangAPValueLValueBase_dyn_cast_Expr(lval_base); - if (expr) |e| { - return (try transExpr(rp, &rp.c.global_scope.base, e, .used, .r_value)).node; - } - try emitWarning(rp.c, source_loc, "TODO handle initializer LValue ValueDecl", .{}); - }, - .Float => try emitWarning(rp.c, source_loc, "unsupported initializer value kind: Float", .{}), - .ComplexInt => try emitWarning(rp.c, source_loc, "unsupported initializer value kind: ComplexInt", .{}), - .ComplexFloat => try emitWarning(rp.c, source_loc, "Tunsupported initializer value kind: ComplexFloat", .{}), - .Vector => try emitWarning(rp.c, source_loc, "unsupported initializer value kind: Vector", .{}), - .Struct => try emitWarning(rp.c, source_loc, "unsupported initializer value kind: Struct", .{}), - .Union => try emitWarning(rp.c, source_loc, "unsupported initializer value kind: Union", .{}), - .MemberPointer => try emitWarning(rp.c, source_loc, "unsupported initializer value kind: MemberPointer", .{}), - .AddrLabelDiff => try emitWarning(rp.c, source_loc, "unsupported initializer value kind: AddrLabelDiff", .{}), - .Indeterminate => try emitWarning(rp.c, source_loc, "unsupported initializer value kind: Indeterminate", .{}), - .FixedPoint => try emitWarning(rp.c, source_loc, "unsupported initializer value kind: FixedPoint", .{}), - } - return error.UnsupportedTranslation; -} - const FnDeclContext = struct { fn_name: []const u8, has_body: bool, diff --git a/src/zig_clang.cpp b/src/zig_clang.cpp index 3c04a2dc8a..86ef17ffbe 100644 --- a/src/zig_clang.cpp +++ b/src/zig_clang.cpp @@ -1825,6 +1825,23 @@ bool ZigClangExpr_EvaluateAsConstantExpr(const ZigClangExpr *self, ZigClangExprE return true; } +const ZigClangExpr *ZigClangInitListExpr_getInit(const ZigClangInitListExpr *self, unsigned i) { + auto casted = reinterpret_cast(self); + const clang::Expr *result = casted->getInit(i); + return reinterpret_cast(result); +} + +const ZigClangExpr *ZigClangInitListExpr_getArrayFiller(const ZigClangInitListExpr *self) { + auto casted = reinterpret_cast(self); + const clang::Expr *result = casted->getArrayFiller(); + return reinterpret_cast(result); +} + +unsigned ZigClangInitListExpr_getNumInits(const ZigClangInitListExpr *self) { + auto casted = reinterpret_cast(self); + return casted->getNumInits(); +} + ZigClangAPValueKind ZigClangAPValue_getKind(const ZigClangAPValue *self) { auto casted = reinterpret_cast(self); return (ZigClangAPValueKind)casted->getKind(); @@ -2065,6 +2082,11 @@ const ZigClangAPValue * ZigClangVarDecl_evaluateValue(const struct ZigClangVarDe return reinterpret_cast(result); } +enum ZigClangStorageClass ZigClangVarDecl_getStorageClass(const struct ZigClangVarDecl *self) { + auto casted = reinterpret_cast(self); + return (ZigClangStorageClass)casted->getStorageClass(); +} + enum ZigClangBuiltinTypeKind ZigClangBuiltinType_getKind(const struct ZigClangBuiltinType *self) { auto casted = reinterpret_cast(self); return (ZigClangBuiltinTypeKind)casted->getKind(); diff --git a/src/zig_clang.h b/src/zig_clang.h index c4c5c378eb..cf60fdfca9 100644 --- a/src/zig_clang.h +++ b/src/zig_clang.h @@ -144,6 +144,7 @@ struct ZigClangUnaryOperator; struct ZigClangValueDecl; struct ZigClangVarDecl; struct ZigClangWhileStmt; +struct ZigClangInitListExpr; typedef struct ZigClangStmt *const * ZigClangCompoundStmt_const_body_iterator; typedef struct ZigClangDecl *const * ZigClangDeclStmt_const_decl_iterator; @@ -904,6 +905,7 @@ ZIG_EXTERN_C bool ZigClangVarDecl_isFileVarDecl(const struct ZigClangVarDecl *); ZIG_EXTERN_C bool ZigClangVarDecl_hasInit(const struct ZigClangVarDecl *); ZIG_EXTERN_C const struct ZigClangAPValue *ZigClangVarDecl_evaluateValue(const struct ZigClangVarDecl *); ZIG_EXTERN_C struct ZigClangQualType ZigClangVarDecl_getTypeSourceInfo_getType(const struct ZigClangVarDecl *); +ZIG_EXTERN_C enum ZigClangStorageClass ZigClangVarDecl_getStorageClass(const struct ZigClangVarDecl *self); ZIG_EXTERN_C bool ZigClangSourceLocation_eq(struct ZigClangSourceLocation a, struct ZigClangSourceLocation b); @@ -939,6 +941,10 @@ ZIG_EXTERN_C bool ZigClangExpr_EvaluateAsFloat(const struct ZigClangExpr *self, ZIG_EXTERN_C bool ZigClangExpr_EvaluateAsConstantExpr(const struct ZigClangExpr *, struct ZigClangExprEvalResult *, ZigClangExpr_ConstExprUsage, const struct ZigClangASTContext *); +ZIG_EXTERN_C const ZigClangExpr *ZigClangInitListExpr_getInit(const ZigClangInitListExpr *, unsigned); +ZIG_EXTERN_C const ZigClangExpr *ZigClangInitListExpr_getArrayFiller(const ZigClangInitListExpr *); +ZIG_EXTERN_C unsigned ZigClangInitListExpr_getNumInits(const ZigClangInitListExpr *); + ZIG_EXTERN_C enum ZigClangAPValueKind ZigClangAPValue_getKind(const struct ZigClangAPValue *self); ZIG_EXTERN_C const struct ZigClangAPSInt *ZigClangAPValue_getInt(const struct ZigClangAPValue *self); ZIG_EXTERN_C unsigned ZigClangAPValue_getArrayInitializedElts(const struct ZigClangAPValue *self); diff --git a/test/translate_c.zig b/test/translate_c.zig index 3b067d1bea..704987ece1 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -98,6 +98,16 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub extern fn d() void; }); + cases.add_2("variable declarations", + \\extern char arr0[] = "hello"; + \\static char arr1[] = "hello"; + \\char arr2[] = "hello"; + , &[_][]const u8{ + \\pub extern var arr0: [*c]u8 = "hello"; + \\pub var arr1: [*c]u8 = "hello"; + \\pub export var arr2: [*c]u8 = "hello"; + }); + /////////////// Cases for only stage1 which are TODO items for stage2 //////////////// cases.add("typedef of function in struct field", From 41a67126a50e3cfab67c749bfc52ac242694774b Mon Sep 17 00:00:00 2001 From: Vexu Date: Fri, 13 Dec 2019 17:36:18 +0200 Subject: [PATCH 7/8] translate-c-2 typedef --- src-self-hosted/clang.zig | 2 +- src-self-hosted/translate_c.zig | 65 +++++++++++++- test/translate_c.zig | 152 ++++++++++++++++---------------- 3 files changed, 139 insertions(+), 80 deletions(-) diff --git a/src-self-hosted/clang.zig b/src-self-hosted/clang.zig index 2ed011cc1e..eebedd0be9 100644 --- a/src-self-hosted/clang.zig +++ b/src-self-hosted/clang.zig @@ -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; diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index a4874d92e3..b3770d1ab7 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -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 { diff --git a/test/translate_c.zig b/test/translate_c.zig index 704987ece1..b83c470637 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -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; From 45abfa9e7189e5d87d4d49763399531973c2f899 Mon Sep 17 00:00:00 2001 From: Vexu Date: Fri, 13 Dec 2019 18:55:34 +0200 Subject: [PATCH 8/8] revert removal of translate mode in stage 1 --- src/codegen.cpp | 8 ++- src/ir.cpp | 2 +- src/translate_c.cpp | 10 ++- src/translate_c.hpp | 7 +- test/tests.zig | 23 +++++++ test/translate_c.zig | 148 ++++++++++++++++++++++--------------------- 6 files changed, 119 insertions(+), 79 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 0ba2c23dbe..3604a1b019 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -9020,6 +9020,10 @@ void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_us init(g); + TranslateMode trans_mode = buf_ends_with_str(full_path, ".h") ? + TranslateModeImport : TranslateModeTranslate; + + ZigList clang_argv = {0}; add_cc_args(g, clang_argv, nullptr, true); @@ -9045,8 +9049,8 @@ void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_us err = stage2_translate_c(&ast, &errors_ptr, &errors_len, &clang_argv.at(0), &clang_argv.last(), resources_path); } else { - err = parse_h_file(g, &root_node, &errors_ptr, &errors_len, &clang_argv.at(0), - &clang_argv.last(), resources_path); + err = parse_h_file(g, &root_node, &errors_ptr, &errors_len, &clang_argv.at(0), &clang_argv.last(), + trans_mode, resources_path); } if (err == ErrorCCompileErrors && errors_len > 0) { diff --git a/src/ir.cpp b/src/ir.cpp index cb854303e4..6f5d3200ff 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -23343,7 +23343,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct const char *resources_path = buf_ptr(ira->codegen->zig_c_headers_dir); if ((err = parse_h_file(ira->codegen, &root_node, &errors_ptr, &errors_len, - &clang_argv.at(0), &clang_argv.last(), resources_path))) + &clang_argv.at(0), &clang_argv.last(), TranslateModeImport, resources_path))) { if (err != ErrorCCompileErrors) { ir_add_error_node(ira, node, buf_sprintf("C import failed: %s", err_str(err))); diff --git a/src/translate_c.cpp b/src/translate_c.cpp index 35830e2990..5b79bfe989 100644 --- a/src/translate_c.cpp +++ b/src/translate_c.cpp @@ -64,6 +64,7 @@ struct TransScopeWhile { struct Context { AstNode *root; + bool want_export; HashMap decl_table; HashMap macro_table; HashMap global_table; @@ -4090,7 +4091,7 @@ static void visit_fn_decl(Context *c, const ZigClangFunctionDecl *fn_decl) { ZigClangStorageClass sc = ZigClangFunctionDecl_getStorageClass(fn_decl); if (sc == ZigClangStorageClass_None) { proto_node->data.fn_proto.visib_mod = VisibModPub; - proto_node->data.fn_proto.is_export = ZigClangFunctionDecl_hasBody(fn_decl); + proto_node->data.fn_proto.is_export = ZigClangFunctionDecl_hasBody(fn_decl) ? c->want_export : false; } else if (sc == ZigClangStorageClass_Extern || sc == ZigClangStorageClass_Static) { proto_node->data.fn_proto.visib_mod = VisibModPub; } else if (sc == ZigClangStorageClass_PrivateExtern) { @@ -5111,11 +5112,16 @@ static void process_preprocessor_entities(Context *c, ZigClangASTUnit *unit) { Error parse_h_file(CodeGen *codegen, AstNode **out_root_node, Stage2ErrorMsg **errors_ptr, size_t *errors_len, const char **args_begin, const char **args_end, - const char *resources_path) + TranslateMode mode, const char *resources_path) { Context context = {0}; Context *c = &context; c->warnings_on = codegen->verbose_cimport; + if (mode == TranslateModeImport) { + c->want_export = false; + } else { + c->want_export = true; + } c->decl_table.init(8); c->macro_table.init(8); c->global_table.init(8); diff --git a/src/translate_c.hpp b/src/translate_c.hpp index 5b7f1dcdd6..6e308dcf04 100644 --- a/src/translate_c.hpp +++ b/src/translate_c.hpp @@ -11,9 +11,14 @@ #include "all_types.hpp" +enum TranslateMode { + TranslateModeImport, + TranslateModeTranslate, +}; + Error parse_h_file(CodeGen *codegen, AstNode **out_root_node, Stage2ErrorMsg **errors_ptr, size_t *errors_len, const char **args_begin, const char **args_end, - const char *resources_path); + TranslateMode mode, const char *resources_path); #endif diff --git a/test/tests.zig b/test/tests.zig index 081136ccad..f8d9df990f 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -1604,6 +1604,16 @@ pub const TranslateCContext = struct { self.addCase(tc); } + pub fn addC( + self: *TranslateCContext, + name: []const u8, + source: []const u8, + expected_lines: []const []const u8, + ) void { + const tc = self.create(false, "source.c", name, source, expected_lines); + self.addCase(tc); + } + pub fn add_both( self: *TranslateCContext, name: []const u8, @@ -1617,6 +1627,19 @@ pub const TranslateCContext = struct { } } + pub fn addC_both( + self: *TranslateCContext, + name: []const u8, + source: []const u8, + expected_lines: []const []const u8, + ) void { + for ([_]bool{ false, true }) |stage2| { + const tc = self.create(false, "source.c", name, source, expected_lines); + tc.stage2 = stage2; + self.addCase(tc); + } + } + pub fn add_2( self: *TranslateCContext, name: []const u8, diff --git a/test/translate_c.zig b/test/translate_c.zig index b83c470637..86f7c85e92 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -1,9 +1,11 @@ const tests = @import("tests.zig"); const builtin = @import("builtin"); -// add_both - test for stage1 and stage2 -// add - test stage1 only +// add_both - test for stage1 and stage2, in #include mode +// add - test stage1 only, in #include mode // add_2 - test stage2 only +// addC_both - test for stage1 and stage2, in -c mode +// addC - test stage1 only, in -c mode pub fn addCases(cases: *tests.TranslateCContext) void { /////////////// Cases that pass for both stage1/stage2 //////////////// @@ -15,7 +17,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub extern fn bar() c_int; }); - cases.add_both("simple var decls", + cases.addC_both("simple var decls", \\void foo(void) { \\ int a; \\ char b = 123; @@ -31,7 +33,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add_both("ignore result, explicit function arguments", + cases.addC_both("ignore result, explicit function arguments", \\void foo(void) { \\ int a; \\ 1; @@ -51,7 +53,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add_both("variables", + cases.addC_both("variables", \\extern int extern_var; \\static const int int_var = 13; , &[_][]const u8{ @@ -66,7 +68,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub var v0: [*c]const u8 = "0.0.0"; }); - cases.add_both("static incomplete array inside function", + cases.addC_both("static incomplete array inside function", \\void foo(void) { \\ static const char v2[] = "2.2.2"; \\} @@ -76,7 +78,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add_both("simple function definition", + cases.addC_both("simple function definition", \\void foo(void) {} \\static void bar(void) {} , &[_][]const u8{ @@ -104,7 +106,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub const baz = c_int; }); - cases.add_both("casting pointers to ints and ints to pointers", + cases.addC_both("casting pointers to ints and ints to pointers", \\void foo(void); \\void bar(void) { \\ void *func_ptr = foo; @@ -124,7 +126,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub extern fn foo() noreturn; }); - cases.add_both("add, sub, mul, div, rem", + cases.addC_both("add, sub, mul, div, rem", \\int s(int a, int b) { \\ int c; \\ c = a + b; @@ -284,7 +286,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ __PRETTY_FUNCTION__; \\} , &[_][]const u8{ - \\pub export fn foo() void { + \\pub fn foo() void { \\ _ = "foo"; \\ _ = "foo"; \\ _ = "void foo(void)"; @@ -301,7 +303,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ a = 1; \\} , &[_][]const u8{ - \\pub export fn foo() void { + \\pub fn foo() void { \\ var a: c_int = undefined; \\ _ = 1; \\ _ = "hey"; @@ -316,7 +318,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ for (int x = 0; x < 10; x++); \\} , &[_][]const u8{ - \\pub export fn foo() void { + \\pub fn foo() void { \\ { \\ var x: c_int = 0; \\ while (x < 10) : (x += 1) {} @@ -329,7 +331,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ do ; while (1); \\} , &[_][]const u8{ // TODO this should be if (1 != 0) break - \\pub export fn foo() void { + \\pub fn foo() void { \\ while (true) { \\ {} \\ if (!1) break; @@ -342,7 +344,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ for (;;); \\} , &[_][]const u8{ - \\pub export fn foo() void { + \\pub fn foo() void { \\ while (true) {} \\} }); @@ -352,7 +354,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ while (1); \\} , &[_][]const u8{ - \\pub export fn foo() void { + \\pub fn foo() void { \\ while (1 != 0) {} \\} }); @@ -392,7 +394,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub extern fn baz(a: i8, b: i16, c: i32, d: i64) void; }); - cases.add("simple function", + cases.addC("simple function", \\int abs(int a) { \\ return a < 0 ? -a : a; \\} @@ -690,7 +692,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub const LUA_GLOBALSINDEX = -10002; }); - cases.add("post increment", + cases.addC("post increment", \\unsigned foo1(unsigned a) { \\ a++; \\ return a; @@ -712,7 +714,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add("shift right assign", + cases.addC("shift right assign", \\int log2(unsigned a) { \\ int i = 0; \\ while (a > 0) { @@ -731,7 +733,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add("if statement", + cases.addC("if statement", \\int max(int a, int b) { \\ if (a < b) \\ return b; @@ -751,7 +753,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add("==, !=", + cases.addC("==, !=", \\int max(int a, int b) { \\ if (a == b) \\ return a; @@ -767,7 +769,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add("bitwise binary operators", + cases.addC("bitwise binary operators", \\int max(int a, int b) { \\ return (a & b) ^ (a | b); \\} @@ -777,7 +779,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add("logical and, logical or", + cases.addC("logical and, logical or", \\int max(int a, int b) { \\ if (a < b || a == b) \\ return b; @@ -793,7 +795,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add("logical and, logical or on none bool values", + cases.addC("logical and, logical or on none bool values", \\int and_or_none_bool(int a, float b, void *c) { \\ if (a && b) return 0; \\ if (b && c) return 1; @@ -815,7 +817,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add("assign", + cases.addC("assign", \\int max(int a) { \\ int tmp; \\ tmp = a; @@ -830,7 +832,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add("chaining assign", + cases.addC("chaining assign", \\void max(int a) { \\ int b, c; \\ c = b = a; @@ -847,7 +849,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add("shift right assign with a fixed size type", + cases.addC("shift right assign with a fixed size type", \\#include \\int log2(uint32_t a) { \\ int i = 0; @@ -877,7 +879,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub const Two = 1; }); - cases.add("function call", + cases.addC("function call", \\static void bar(void) { } \\static int baz(void) { return 0; } \\void foo(void) { @@ -895,7 +897,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add("field access expression", + cases.addC("field access expression", \\struct Foo { \\ int field; \\}; @@ -911,7 +913,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add("null statements", + cases.addC("null statements", \\void foo(void) { \\ ;;;;; \\} @@ -931,7 +933,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub var array: [100]c_int = undefined; }); - cases.add("array access", + cases.addC("array access", \\int array[100]; \\int foo(int index) { \\ return array[index]; @@ -943,7 +945,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add("c style cast", + cases.addC("c style cast", \\int float_to_int(float a) { \\ return (int)a; \\} @@ -953,7 +955,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add("void cast", + cases.addC("void cast", \\void foo(int a) { \\ (void) a; \\} @@ -963,7 +965,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add("implicit cast to void *", + cases.addC("implicit cast to void *", \\void *foo(unsigned short *x) { \\ return x; \\} @@ -973,7 +975,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add("sizeof", + cases.addC("sizeof", \\#include \\size_t size_of(void) { \\ return sizeof(int); @@ -984,7 +986,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add("null pointer implicit cast", + cases.addC("null pointer implicit cast", \\int* foo(void) { \\ return 0; \\} @@ -994,7 +996,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add("comma operator", + cases.addC("comma operator", \\int foo(void) { \\ return 1, 2; \\} @@ -1007,7 +1009,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add("statement expression", + cases.addC("statement expression", \\int foo(void) { \\ return ({ \\ int a = 1; @@ -1023,7 +1025,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add("__extension__ cast", + cases.addC("__extension__ cast", \\int foo(void) { \\ return __extension__ 1; \\} @@ -1033,7 +1035,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add("bitshift", + cases.addC("bitshift", \\int foo(void) { \\ return (1 << 2) >> 1; \\} @@ -1043,7 +1045,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add("compound assignment operators", + cases.addC("compound assignment operators", \\void foo(void) { \\ int a = 0; \\ a += (a += 1); @@ -1101,7 +1103,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add("compound assignment operators unsigned", + cases.addC("compound assignment operators unsigned", \\void foo(void) { \\ unsigned a = 0; \\ a += (a += 1); @@ -1159,7 +1161,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add("post increment/decrement", + cases.addC("post increment/decrement", \\void foo(void) { \\ int i = 0; \\ unsigned u = 0; @@ -1207,7 +1209,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add("pre increment/decrement", + cases.addC("pre increment/decrement", \\void foo(void) { \\ int i = 0; \\ unsigned u = 0; @@ -1251,7 +1253,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add("do loop", + cases.addC("do loop", \\void foo(void) { \\ int a = 2; \\ do { @@ -1278,7 +1280,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add("deref function pointer", + cases.addC("deref function pointer", \\void foo(void) {} \\int baz(void) { return 0; } \\void bar(void) { @@ -1308,7 +1310,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add("normal deref", + cases.addC("normal deref", \\void foo(int *x) { \\ *x = 1; \\} @@ -1339,7 +1341,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ return *ptr; \\} , &[_][]const u8{ - \\pub export fn foo() c_int { + \\pub fn foo() c_int { \\ var x: c_int = 1234; \\ var ptr: [*c]c_int = &x; \\ return ptr.?.*; @@ -1351,7 +1353,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ return "bar"; \\} , &[_][]const u8{ - \\pub export fn foo() [*c]const u8 { + \\pub fn foo() [*c]const u8 { \\ return "bar"; \\} }); @@ -1361,7 +1363,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ return; \\} , &[_][]const u8{ - \\pub export fn foo() void { + \\pub fn foo() void { \\ return; \\} }); @@ -1371,7 +1373,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ for (int i = 0; i < 10; i += 1) { } \\} , &[_][]const u8{ - \\pub export fn foo() void { + \\pub fn foo() void { \\ { \\ var i: c_int = 0; \\ while (i < 10) : (i += 1) {} @@ -1384,7 +1386,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ for (;;) { } \\} , &[_][]const u8{ - \\pub export fn foo() void { + \\pub fn foo() void { \\ while (true) {} \\} }); @@ -1396,7 +1398,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ } \\} , &[_][]const u8{ - \\pub export fn foo() void { + \\pub fn foo() void { \\ while (true) { \\ break; \\ } @@ -1410,7 +1412,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ } \\} , &[_][]const u8{ - \\pub export fn foo() void { + \\pub fn foo() void { \\ while (true) { \\ continue; \\ } @@ -1465,7 +1467,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ return x; \\} , &[_][]const u8{ - \\pub export fn foo() c_int { + \\pub fn foo() c_int { \\ var x: c_int = 1; \\ { \\ var x_0: c_int = 2; @@ -1490,7 +1492,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ return ~x; \\} , &[_][]const u8{ - \\pub export fn foo(x: c_int) c_int { + \\pub fn foo(x: c_int) c_int { \\ return ~x; \\} }); @@ -1503,7 +1505,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ return !c; \\} , &[_][]const u8{ - \\pub export fn foo(a: c_int, b: f32, c: ?*c_void) c_int { + \\pub fn foo(a: c_int, b: f32, c: ?*c_void) c_int { \\ return !(a == 0); \\ return !(a != 0); \\ return !(b != 0); @@ -1516,7 +1518,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ return u32; \\} , &[_][]const u8{ - \\pub export fn foo(u32_0: c_int) c_int { + \\pub fn foo(u32_0: c_int) c_int { \\ return u32_0; \\} }); @@ -1545,7 +1547,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ B, \\ C, \\}; - \\pub export fn if_none_bool(a: c_int, b: f32, c: ?*c_void, d: enum_SomeEnum) c_int { + \\pub fn if_none_bool(a: c_int, b: f32, c: ?*c_void, d: enum_SomeEnum) c_int { \\ if (a != 0) return 0; \\ if (b != 0) return 1; \\ if (c != null) return 2; @@ -1562,7 +1564,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ return 3; \\} , &[_][]const u8{ - \\pub export fn while_none_bool(a: c_int, b: f32, c: ?*c_void) c_int { + \\pub fn while_none_bool(a: c_int, b: f32, c: ?*c_void) c_int { \\ while (a != 0) return 0; \\ while (b != 0) return 1; \\ while (c != null) return 2; @@ -1578,7 +1580,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ return 3; \\} , &[_][]const u8{ - \\pub export fn for_none_bool(a: c_int, b: f32, c: ?*c_void) c_int { + \\pub fn for_none_bool(a: c_int, b: f32, c: ?*c_void) c_int { \\ while (a != 0) return 0; \\ while (b != 0) return 1; \\ while (c != null) return 2; @@ -1602,7 +1604,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ } \\} , &[_][]const u8{ - \\pub export fn switch_fn(i: c_int) c_int { + \\pub fn switch_fn(i: c_int) c_int { \\ var res: c_int = 0; \\ __switch: { \\ __case_2: { @@ -1628,7 +1630,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add( + cases.addC( "u integer suffix after 0 (zero) in macro definition", "#define ZERO 0U", &[_][]const u8{ @@ -1636,7 +1638,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { }, ); - cases.add( + cases.addC( "l integer suffix after 0 (zero) in macro definition", "#define ZERO 0L", &[_][]const u8{ @@ -1644,7 +1646,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { }, ); - cases.add( + cases.addC( "ul integer suffix after 0 (zero) in macro definition", "#define ZERO 0UL", &[_][]const u8{ @@ -1652,7 +1654,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { }, ); - cases.add( + cases.addC( "lu integer suffix after 0 (zero) in macro definition", "#define ZERO 0LU", &[_][]const u8{ @@ -1660,7 +1662,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { }, ); - cases.add( + cases.addC( "ll integer suffix after 0 (zero) in macro definition", "#define ZERO 0LL", &[_][]const u8{ @@ -1668,7 +1670,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { }, ); - cases.add( + cases.addC( "ull integer suffix after 0 (zero) in macro definition", "#define ZERO 0ULL", &[_][]const u8{ @@ -1676,7 +1678,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { }, ); - cases.add( + cases.addC( "llu integer suffix after 0 (zero) in macro definition", "#define ZERO 0LLU", &[_][]const u8{ @@ -1684,7 +1686,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { }, ); - cases.add( + cases.addC( "bitwise not on u-suffixed 0 (zero) in macro definition", "#define NOT_ZERO (~0U)", &[_][]const u8{ @@ -1692,7 +1694,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { }, ); - cases.add("implicit casts", + cases.addC("implicit casts", \\#include \\ \\void fn_int(int x); @@ -1747,7 +1749,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add("pointer conversion with different alignment", + cases.addC("pointer conversion with different alignment", \\void test_ptr_cast() { \\ void *p; \\ { @@ -1781,7 +1783,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add("escape sequences", + cases.addC("escape sequences", \\const char *escapes() { \\char a = '\'', \\ b = '\\', @@ -1825,7 +1827,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { } /////////////// Cases for only stage1 because stage2 behavior is better //////////////// - cases.add("Parameterless function prototypes", + cases.addC("Parameterless function prototypes", \\void foo() {} \\void bar(void) {} , &[_][]const u8{