diff --git a/src-self-hosted/clang.zig b/src-self-hosted/clang.zig index 1c8c0928b3..eebedd0be9 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(); @@ -73,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, @@ -733,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; @@ -747,17 +749,19 @@ 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; 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; @@ -766,6 +770,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; @@ -863,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, @@ -916,6 +923,9 @@ 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_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; @@ -930,7 +940,10 @@ 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; pub extern fn ZigClangDeclRefExpr_getDecl(*const ZigClangDeclRefExpr) *const ZigClangValueDecl; pub extern fn ZigClangParenType_getInnerType(*const ZigClangParenType) ZigClangQualType; @@ -957,6 +970,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/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..b3770d1ab7 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).?, }; @@ -228,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", .{}); @@ -237,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)); @@ -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 @@ -310,6 +302,130 @@ 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); + 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); + + const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl); + const storage_class = ZigClangVarDecl_getStorageClass(var_decl); + const is_const = ZigClangQualType_isConstQualified(qual_type); + + 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; + + 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, + }; + + 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 translate initializer", .{}); + }, + error.OutOfMemory => |e| return e, + }; + break :blk res.node; + } else + try transCreateNodeUndefinedLiteral(c); + } else if (storage_class != .Extern) { + return failDecl(c, var_decl_loc, var_name, "non-extern variable has no initializer", .{}); + } + + 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); +} + +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, @@ -339,6 +455,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, @@ -564,7 +681,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 @@ -589,15 +706,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(c); const semicolon_token = try appendToken(c, .Semicolon, ";"); const node = try c.a().create(ast.Node.VarDecl); @@ -687,7 +797,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( @@ -868,6 +978,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) { @@ -1233,6 +1425,40 @@ 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 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 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, @@ -1316,6 +1542,47 @@ 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; + }, + .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; + }, + .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}); @@ -1323,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, @@ -1473,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) { @@ -1568,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/src/codegen.cpp b/src/codegen.cpp index a3f3eb622f..cad67e3788 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -9016,8 +9016,8 @@ 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; + TranslateMode trans_mode = buf_ends_with_str(full_path, ".h") ? + TranslateModeImport : TranslateModeTranslate; ZigList clang_argv = {0}; @@ -9043,7 +9043,7 @@ 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); diff --git a/src/ir.cpp b/src/ir.cpp index bdf8c33bc2..da208b62c6 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -23303,7 +23303,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(), 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 eb207231f0..5b79bfe989 100644 --- a/src/translate_c.cpp +++ b/src/translate_c.cpp @@ -64,7 +64,6 @@ struct TransScopeWhile { struct Context { AstNode *root; - VisibMod visib_mod; bool want_export; HashMap decl_table; HashMap macro_table; @@ -367,7 +366,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 +378,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 +4090,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.visib_mod = VisibModPub; 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 = 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,16 +5112,14 @@ 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) + TranslateMode mode, const char *resources_path) { Context context = {0}; Context *c = &context; c->warnings_on = codegen->verbose_cimport; - if (mode == Stage2TranslateModeImport) { - c->visib_mod = VisibModPub; + if (mode == TranslateModeImport) { c->want_export = false; } else { - c->visib_mod = VisibModPub; c->want_export = true; } c->decl_table.init(8); diff --git a/src/translate_c.hpp b/src/translate_c.hpp index 4eac26ddb5..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, - Stage2TranslateMode mode, const char *resources_path); + TranslateMode mode, 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); 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/tests.zig b/test/tests.zig index 7326b62054..f8d9df990f 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -1651,17 +1651,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..86f7c85e92 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -3,10 +3,9 @@ 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_2 - test stage2 only // 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 { /////////////// Cases that pass for both stage1/stage2 //////////////// @@ -18,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; @@ -26,7 +25,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; @@ -34,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; @@ -44,7 +43,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,42 +53,139 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); + cases.addC_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.addC_both("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.addC_both("simple function definition", + \\void foo(void) {} + \\static void bar(void) {} + , &[_][]const u8{ + \\pub export fn foo() 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.addC_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.addC_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 //////////////// - // 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("simple function definition", - // \\void foo(void) {} - // \\static void bar(void) {} - // , - // \\pub export fn foo() void {} - // \\pub extern fn bar() void {} - // ); - - cases.add_2("parameterless function prototypes", + cases.add_2("Parameterless function prototypes", \\void a() {} \\void b(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; }); + 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", @@ -120,34 +216,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\}; }); - cases.add_both("simple function definition", - \\void foo(void) {} - \\static void bar(void) {} - , &[_][]const u8{ - \\pub fn foo() void {} - \\pub fn bar() void {} - }); - cases.add("macro with left shift", \\#define REDISMODULE_READ (1<<0) , &[_][]const u8{ \\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 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", @@ -320,12 +394,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.addC("simple function", \\int abs(int a) { \\ return a < 0 ? -a : a; @@ -482,15 +550,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; \\ @@ -511,15 +570,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 @@ -719,42 +769,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC_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.addC("bitwise binary operators", \\int max(int a, int b) { \\ return (a & b) ^ (a | b); @@ -1147,17 +1161,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC("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.addC("post increment/decrement", \\void foo(void) { \\ int i = 0; @@ -1520,22 +1523,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - 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 { - \\ const v2: [*c]const u8 = "2.2.2"; - \\} - }); - cases.add("macro pointer cast", \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE) , &[_][]const u8{