From 5f4c3e6557b6ffd654fad5ef3928e5f21db56a50 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 10 May 2019 23:35:46 -0400 Subject: [PATCH] stage2 translate-c: simple function definitions See #1964 --- src-self-hosted/clang.zig | 26 +++-- src-self-hosted/translate_c.zig | 186 ++++++++++++++++++++++++++------ src/translate_c.cpp | 16 +-- src/zig_clang.cpp | 18 ++++ src/zig_clang.h | 7 ++ test/translate_c.zig | 6 ++ 6 files changed, 210 insertions(+), 49 deletions(-) diff --git a/src-self-hosted/clang.zig b/src-self-hosted/clang.zig index dd9e49b05b..92fe7b7cd3 100644 --- a/src-self-hosted/clang.zig +++ b/src-self-hosted/clang.zig @@ -12,7 +12,7 @@ pub const struct_ZigClangCStyleCastExpr = @OpaqueType(); pub const struct_ZigClangCallExpr = @OpaqueType(); pub const struct_ZigClangCaseStmt = @OpaqueType(); pub const struct_ZigClangCompoundAssignOperator = @OpaqueType(); -pub const struct_ZigClangCompoundStmt = @OpaqueType(); +pub const ZigClangCompoundStmt = @OpaqueType(); pub const struct_ZigClangConditionalOperator = @OpaqueType(); pub const struct_ZigClangConstantArrayType = @OpaqueType(); pub const struct_ZigClangContinueStmt = @OpaqueType(); @@ -33,7 +33,7 @@ pub const struct_ZigClangFieldDecl = @OpaqueType(); pub const struct_ZigClangFileID = @OpaqueType(); pub const struct_ZigClangForStmt = @OpaqueType(); pub const struct_ZigClangFullSourceLoc = @OpaqueType(); -pub const struct_ZigClangFunctionDecl = @OpaqueType(); +pub const ZigClangFunctionDecl = @OpaqueType(); pub const struct_ZigClangFunctionProtoType = @OpaqueType(); pub const struct_ZigClangIfStmt = @OpaqueType(); pub const struct_ZigClangImplicitCastExpr = @OpaqueType(); @@ -488,12 +488,12 @@ pub extern fn ZigClangQualType_isRestrictQualified(arg0: struct_ZigClangQualType pub extern fn ZigClangType_getTypeClass(self: ?*const struct_ZigClangType) ZigClangTypeClass; pub extern fn ZigClangType_isVoidType(self: ?*const struct_ZigClangType) bool; pub extern fn ZigClangType_getTypeClassName(self: *const struct_ZigClangType) [*]const u8; -pub extern fn ZigClangStmt_getBeginLoc(self: ?*const struct_ZigClangStmt) struct_ZigClangSourceLocation; +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 ZigClangExpr_getBeginLoc(self: *const struct_ZigClangExpr) struct_ZigClangSourceLocation; 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; @@ -510,11 +510,12 @@ pub extern fn ZigClangAPSInt_getNumWords(self: ?*const struct_ZigClangAPSInt) c_ pub extern fn ZigClangAPValueLValueBase_dyn_cast_Expr(self: struct_ZigClangAPValueLValueBase) ?*const struct_ZigClangExpr; pub extern fn ZigClangASTUnit_delete(arg0: ?*struct_ZigClangASTUnit) void; -pub extern fn ZigClangFunctionDecl_getType(self: *const struct_ZigClangFunctionDecl) struct_ZigClangQualType; -pub extern fn ZigClangFunctionDecl_getLocation(self: *const struct_ZigClangFunctionDecl) struct_ZigClangSourceLocation; -pub extern fn ZigClangFunctionDecl_hasBody(self: *const struct_ZigClangFunctionDecl) bool; -pub extern fn ZigClangFunctionDecl_getStorageClass(self: *const struct_ZigClangFunctionDecl) ZigClangStorageClass; -pub extern fn ZigClangFunctionDecl_getParamDecl(self: *const struct_ZigClangFunctionDecl, i: c_uint) *const struct_ZigClangParmVarDecl; +pub extern fn ZigClangFunctionDecl_getType(self: *const ZigClangFunctionDecl) struct_ZigClangQualType; +pub extern fn ZigClangFunctionDecl_getLocation(self: *const ZigClangFunctionDecl) struct_ZigClangSourceLocation; +pub extern fn ZigClangFunctionDecl_hasBody(self: *const ZigClangFunctionDecl) bool; +pub extern fn ZigClangFunctionDecl_getStorageClass(self: *const ZigClangFunctionDecl) ZigClangStorageClass; +pub extern fn ZigClangFunctionDecl_getParamDecl(self: *const ZigClangFunctionDecl, i: c_uint) *const struct_ZigClangParmVarDecl; +pub extern fn ZigClangFunctionDecl_getBody(self: *const ZigClangFunctionDecl) *const struct_ZigClangStmt; pub extern fn ZigClangBuiltinType_getKind(self: *const struct_ZigClangBuiltinType) ZigClangBuiltinTypeKind; @@ -543,7 +544,6 @@ pub const ZigClangCStyleCastExpr = struct_ZigClangCStyleCastExpr; pub const ZigClangCallExpr = struct_ZigClangCallExpr; pub const ZigClangCaseStmt = struct_ZigClangCaseStmt; pub const ZigClangCompoundAssignOperator = struct_ZigClangCompoundAssignOperator; -pub const ZigClangCompoundStmt = struct_ZigClangCompoundStmt; pub const ZigClangConditionalOperator = struct_ZigClangConditionalOperator; pub const ZigClangConstantArrayType = struct_ZigClangConstantArrayType; pub const ZigClangContinueStmt = struct_ZigClangContinueStmt; @@ -564,7 +564,6 @@ pub const ZigClangFieldDecl = struct_ZigClangFieldDecl; pub const ZigClangFileID = struct_ZigClangFileID; pub const ZigClangForStmt = struct_ZigClangForStmt; pub const ZigClangFullSourceLoc = struct_ZigClangFullSourceLoc; -pub const ZigClangFunctionDecl = struct_ZigClangFunctionDecl; pub const ZigClangFunctionProtoType = struct_ZigClangFunctionProtoType; pub const ZigClangIfStmt = struct_ZigClangIfStmt; pub const ZigClangImplicitCastExpr = struct_ZigClangImplicitCastExpr; @@ -860,3 +859,8 @@ pub const ZigClangStorageClass = extern enum { Auto, Register, }; + +pub const ZigClangCompoundStmt_const_body_iterator = [*c]const *struct_ZigClangStmt; + +pub extern fn ZigClangCompoundStmt_body_begin(self: *const ZigClangCompoundStmt) ZigClangCompoundStmt_const_body_iterator; +pub extern fn ZigClangCompoundStmt_body_end(self: *const ZigClangCompoundStmt) ZigClangCompoundStmt_const_body_iterator; diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index b3738dc961..e7d6bfd09c 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -3,6 +3,7 @@ const std = @import("std"); const builtin = @import("builtin"); +const assert = std.debug.assert; const ast = std.zig.ast; const Token = std.zig.Token; use @import("clang.zig"); @@ -21,6 +22,10 @@ pub const Error = error{ OutOfMemory, UnsupportedType, }; +pub const TransError = error{ + OutOfMemory, + UnsupportedTranslation, +}; const DeclTable = std.HashMap(usize, void, addrHash, addrEql); @@ -61,6 +66,27 @@ const Scope = struct { const Block = struct { base: Scope, + block_node: *ast.Node.Block, + + /// Don't forget to set rbrace token later + fn create(c: *Context, parent: *Scope, lbrace_tok: ast.TokenIndex) !*Block { + const block = try c.a().create(Block); + block.* = Block{ + .base = Scope{ + .id = Id.Block, + .parent = parent, + }, + .block_node = try c.a().create(ast.Node.Block), + }; + block.block_node.* = ast.Node.Block{ + .base = ast.Node{ .id = ast.Node.Id.Block }, + .label = null, + .lbrace = lbrace_tok, + .statements = ast.Node.Block.StatementList.init(c.a()), + .rbrace = undefined, + }; + return block; + } }; const Root = struct { @@ -72,6 +98,12 @@ const Scope = struct { }; }; +const TransResult = struct { + node: *ast.Node, + node_scope: *Scope, + child_scope: *Scope, +}; + const Context = struct { tree: *ast.Tree, source_buffer: *std.Buffer, @@ -170,6 +202,14 @@ pub fn translate( _ = try appendToken(&context, .Eof, ""); tree.source = source_buffer.toOwnedSlice(); + if (false) { + std.debug.warn("debug source:\n{}\n==EOF==\ntokens:\n", tree.source); + var i: usize = 0; + while (i < tree.tokens.len) : (i += 1) { + const token = tree.tokens.at(i); + std.debug.warn("{}\n", token); + } + } return tree; } @@ -213,29 +253,107 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { const fn_decl_loc = ZigClangFunctionDecl_getLocation(fn_decl); const fn_qt = ZigClangFunctionDecl_getType(fn_decl); const fn_type = ZigClangQualType_getTypePtr(fn_qt); + var scope = &c.global_scope.base; + const decl_ctx = FnDeclContext{ + .fn_name = fn_name, + .has_body = ZigClangFunctionDecl_hasBody(fn_decl), + .storage_class = ZigClangFunctionDecl_getStorageClass(fn_decl), + .scope = &scope, + }; const proto_node = switch (ZigClangType_getTypeClass(fn_type)) { - .FunctionProto => transFnProto( - rp, - @ptrCast(*const ZigClangFunctionProtoType, fn_type), - fn_decl_loc, - fn_decl, - fn_name, - ) catch |err| switch (err) { - error.UnsupportedType => { - return failDecl(c, fn_decl_loc, fn_name, "unable to resolve prototype of function"); - }, - else => return err, + .FunctionProto => blk: { + const fn_proto_type = @ptrCast(*const ZigClangFunctionProtoType, fn_type); + break :blk transFnProto(rp, fn_proto_type, fn_decl_loc, decl_ctx) catch |err| switch (err) { + error.UnsupportedType => { + return failDecl(c, fn_decl_loc, fn_name, "unable to resolve prototype of function"); + }, + error.OutOfMemory => return error.OutOfMemory, + }; }, .FunctionNoProto => return failDecl(c, fn_decl_loc, fn_name, "TODO support functions with no prototype"), else => unreachable, }; - if (!ZigClangFunctionDecl_hasBody(fn_decl)) { + if (!decl_ctx.has_body) { const semi_tok = try appendToken(c, .Semicolon, ";"); return addTopLevelDecl(c, fn_name, &proto_node.base); } - try emitWarning(c, fn_decl_loc, "TODO implement function body translation"); + // actual function definition with body + const body_stmt = ZigClangFunctionDecl_getBody(fn_decl); + const result = transStmt(rp, scope, body_stmt, .unused, .r_value) catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + error.UnsupportedTranslation => return failDecl(c, fn_decl_loc, fn_name, "unable to translate function"), + }; + assert(result.node.id == ast.Node.Id.Block); + proto_node.body_node = result.node; + + return addTopLevelDecl(c, fn_name, &proto_node.base); +} + +const ResultUsed = enum { + used, + unused, +}; + +const LRValue = enum { + l_value, + r_value, +}; + +fn transStmt( + rp: RestorePoint, + scope: *Scope, + stmt: *const ZigClangStmt, + result_used: ResultUsed, + lrvalue: LRValue, +) !TransResult { + const sc = ZigClangStmt_getStmtClass(stmt); + switch (sc) { + .CompoundStmtClass => return transCompoundStmt(rp, scope, @ptrCast(*const ZigClangCompoundStmt, stmt)), + else => { + return revertAndWarn( + rp, + error.UnsupportedTranslation, + ZigClangStmt_getBeginLoc(stmt), + "TODO implement translation of stmt class {}", + @tagName(sc), + ); + }, + } +} + +fn transCompoundStmtInline( + rp: RestorePoint, + parent_scope: *Scope, + stmt: *const ZigClangCompoundStmt, + block_node: *ast.Node.Block, +) TransError!TransResult { + var it = ZigClangCompoundStmt_body_begin(stmt); + const end_it = ZigClangCompoundStmt_body_end(stmt); + var scope = parent_scope; + while (it != end_it) : (it += 1) { + const result = try transStmt(rp, scope, it.*, .unused, .r_value); + scope = result.child_scope; + try block_node.statements.push(result.node); + } + return TransResult{ + .node = &block_node.base, + .child_scope = scope, + .node_scope = scope, + }; +} + +fn transCompoundStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundStmt) !TransResult { + const lbrace_tok = try appendToken(rp.c, .LBrace, "{"); + const block_scope = try Scope.Block.create(rp.c, scope, lbrace_tok); + const inline_result = try transCompoundStmtInline(rp, &block_scope.base, stmt, block_scope.block_node); + block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}"); + return TransResult{ + .node = &block_scope.block_node.base, + .node_scope = inline_result.node_scope, + .child_scope = inline_result.child_scope, + }; } fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: *ast.Node) !void { @@ -299,7 +417,7 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour }, .FunctionProto => { const fn_proto_ty = @ptrCast(*const ZigClangFunctionProtoType, ty); - const fn_proto = try transFnProto(rp, fn_proto_ty, source_loc, null, null); + const fn_proto = try transFnProto(rp, fn_proto_ty, source_loc, null); return &fn_proto.base; }, else => { @@ -309,12 +427,18 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour } } +const FnDeclContext = struct { + fn_name: []const u8, + has_body: bool, + storage_class: ZigClangStorageClass, + scope: **Scope, +}; + fn transFnProto( rp: RestorePoint, fn_proto_ty: *const ZigClangFunctionProtoType, source_loc: ZigClangSourceLocation, - opt_fn_decl: ?*const ZigClangFunctionDecl, - fn_name: ?[]const u8, + fn_decl_context: ?FnDeclContext, ) !*ast.Node.FnProto { const fn_ty = @ptrCast(*const ZigClangFunctionType, fn_proto_ty); const cc = switch (ZigClangFunctionType_getCallConv(fn_ty)) { @@ -351,13 +475,11 @@ fn transFnProto( const pub_tok = try appendToken(rp.c, .Keyword_pub, "pub"); const cc_tok = if (cc == .Stdcall) try appendToken(rp.c, .Keyword_stdcallcc, "stdcallcc") else null; const is_export = exp: { - const fn_decl = opt_fn_decl orelse break :exp false; - const has_body = ZigClangFunctionDecl_hasBody(fn_decl); - const storage_class = ZigClangFunctionDecl_getStorageClass(fn_decl); - break :exp switch (storage_class) { + const decl_ctx = fn_decl_context orelse break :exp false; + break :exp switch (decl_ctx.storage_class) { .None => switch (rp.c.mode) { .import => false, - .translate => has_body, + .translate => decl_ctx.has_body, }, .Extern, .Static => false, .PrivateExtern => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported storage class: private extern"), @@ -372,7 +494,7 @@ fn transFnProto( else null; const fn_tok = try appendToken(rp.c, .Keyword_fn, "fn"); - const name_tok = if (fn_name) |n| try appendToken(rp.c, .Identifier, "{}", n) else null; + const name_tok = if (fn_decl_context) |ctx| try appendToken(rp.c, .Identifier, ctx.fn_name) else null; const lparen_tok = try appendToken(rp.c, .LParen, "("); const var_args_tok = if (is_var_args) try appendToken(rp.c, .Ellipsis3, "...") else null; const rparen_tok = try appendToken(rp.c, .RParen, ")"); @@ -390,7 +512,7 @@ fn transFnProto( try emitWarning(rp.c, source_loc, "unsupported function proto return type"); return err; }, - else => return err, + error.OutOfMemory => return error.OutOfMemory, }; } } @@ -430,17 +552,17 @@ fn revertAndWarn( } fn emitWarning(c: *Context, loc: ZigClangSourceLocation, comptime format: []const u8, args: ...) !void { - _ = try appendToken(c, .LineComment, "// {}: warning: " ++ format, c.locStr(loc), args); + _ = try appendTokenFmt(c, .LineComment, "// {}: warning: " ++ format, c.locStr(loc), args); } fn failDecl(c: *Context, loc: ZigClangSourceLocation, name: []const u8, comptime format: []const u8, args: ...) !void { // const name = @compileError(msg); const const_tok = try appendToken(c, .Keyword_const, "const"); - const name_tok = try appendToken(c, .Identifier, "{}", name); + const name_tok = try appendToken(c, .Identifier, name); const eq_tok = try appendToken(c, .Equal, "="); const builtin_tok = try appendToken(c, .Builtin, "@compileError"); const lparen_tok = try appendToken(c, .LParen, "("); - const msg_tok = try appendToken(c, .StringLiteral, "\"" ++ format ++ "\"", args); + const msg_tok = try appendTokenFmt(c, .StringLiteral, "\"" ++ format ++ "\"", args); const rparen_tok = try appendToken(c, .RParen, ")"); const semi_tok = try appendToken(c, .Semicolon, ";"); @@ -480,16 +602,20 @@ fn failDecl(c: *Context, loc: ZigClangSourceLocation, name: []const u8, comptime try c.tree.root_node.decls.push(&var_decl_node.base); } -fn appendToken(c: *Context, token_id: Token.Id, comptime format: []const u8, args: ...) !ast.TokenIndex { +fn appendToken(c: *Context, token_id: Token.Id, bytes: []const u8) !ast.TokenIndex { + return appendTokenFmt(c, token_id, "{}", bytes); +} + +fn appendTokenFmt(c: *Context, token_id: Token.Id, comptime format: []const u8, args: ...) !ast.TokenIndex { const S = struct { - fn callback(context: *Context, bytes: []const u8) Error!void { + fn callback(context: *Context, bytes: []const u8) error{OutOfMemory}!void { return context.source_buffer.append(bytes); } }; const start_index = c.source_buffer.len(); errdefer c.source_buffer.shrink(start_index); - try std.fmt.format(c, Error, S.callback, format, args); + try std.fmt.format(c, error{OutOfMemory}, S.callback, format, args); const end_index = c.source_buffer.len(); const token_index = c.tree.tokens.len; const new_token = try c.tree.tokens.addOne(); @@ -506,7 +632,7 @@ fn appendToken(c: *Context, token_id: Token.Id, comptime format: []const u8, arg } fn appendIdentifier(c: *Context, name: []const u8) !*ast.Node { - const token_index = try appendToken(c, .Identifier, "{}", name); + const token_index = try appendToken(c, .Identifier, name); const identifier = try c.a().create(ast.Node.Identifier); identifier.* = ast.Node.Identifier{ .base = ast.Node{ .id = ast.Node.Id.Identifier }, diff --git a/src/translate_c.cpp b/src/translate_c.cpp index 71c0376130..c3c715cb47 100644 --- a/src/translate_c.cpp +++ b/src/translate_c.cpp @@ -1277,15 +1277,15 @@ static AstNode *trans_qual_type(Context *c, ZigClangQualType qt, ZigClangSourceL return trans_type(c, ZigClangQualType_getTypePtr(qt), source_loc); } -static int trans_compound_stmt_inline(Context *c, TransScope *scope, const clang::CompoundStmt *stmt, +static int trans_compound_stmt_inline(Context *c, TransScope *scope, const ZigClangCompoundStmt *stmt, AstNode *block_node, TransScope **out_node_scope) { assert(block_node->type == NodeTypeBlock); - for (clang::CompoundStmt::const_body_iterator it = stmt->body_begin(), end_it = stmt->body_end(); - it != end_it; ++it) + for (ZigClangCompoundStmt_const_body_iterator it = ZigClangCompoundStmt_body_begin(stmt), + end_it = ZigClangCompoundStmt_body_end(stmt); it != end_it; ++it) { AstNode *child_node; - scope = trans_stmt(c, scope, bitcast(*it), &child_node); + scope = trans_stmt(c, scope, *it, &child_node); if (scope == nullptr) return ErrorUnexpected; if (child_node != nullptr) @@ -1297,7 +1297,7 @@ static int trans_compound_stmt_inline(Context *c, TransScope *scope, const clang return ErrorNone; } -static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const clang::CompoundStmt *stmt, +static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const ZigClangCompoundStmt *stmt, TransScope **out_node_scope) { TransScopeBlock *child_scope_block = trans_scope_block_create(c, scope); @@ -1309,7 +1309,7 @@ static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const clang:: static AstNode *trans_stmt_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::StmtExpr *stmt, TransScope **out_node_scope) { - AstNode *block = trans_compound_stmt(c, scope, stmt->getSubStmt(), out_node_scope); + AstNode *block = trans_compound_stmt(c, scope, (const ZigClangCompoundStmt *)stmt->getSubStmt(), out_node_scope); if (block == nullptr) return block; assert(block->type == NodeTypeBlock); @@ -3220,7 +3220,7 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const cl AstNode *body_node; const ZigClangStmt *body_stmt = bitcast(stmt->getBody()); if (ZigClangStmt_getStmtClass(body_stmt) == ZigClangStmt_CompoundStmtClass) { - if (trans_compound_stmt_inline(c, &switch_scope->base, (const clang::CompoundStmt *)body_stmt, + if (trans_compound_stmt_inline(c, &switch_scope->base, (const ZigClangCompoundStmt *)body_stmt, block_scope->node, nullptr)) { return nullptr; @@ -3399,7 +3399,7 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const ZigClangStmt *s trans_return_stmt(c, scope, (const clang::ReturnStmt *)stmt)); case ZigClangStmt_CompoundStmtClass: return wrap_stmt(out_node, out_child_scope, scope, - trans_compound_stmt(c, scope, (const clang::CompoundStmt *)stmt, out_node_scope)); + trans_compound_stmt(c, scope, (const ZigClangCompoundStmt *)stmt, out_node_scope)); case ZigClangStmt_IntegerLiteralClass: return wrap_stmt(out_node, out_child_scope, scope, trans_integer_literal(c, result_used, (const clang::IntegerLiteral *)stmt)); diff --git a/src/zig_clang.cpp b/src/zig_clang.cpp index 25e309a63e..b558fa318c 100644 --- a/src/zig_clang.cpp +++ b/src/zig_clang.cpp @@ -1292,6 +1292,14 @@ static clang::APValue::LValueBase bitcast(ZigClangAPValueLValueBase src) { return dest; } +static_assert(sizeof(ZigClangCompoundStmt_const_body_iterator) == sizeof(clang::CompoundStmt::const_body_iterator), ""); +static ZigClangCompoundStmt_const_body_iterator bitcast(clang::CompoundStmt::const_body_iterator src) { + ZigClangCompoundStmt_const_body_iterator dest; + memcpy(&dest, static_cast(&src), sizeof(ZigClangCompoundStmt_const_body_iterator)); + return dest; +} + + ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const ZigClangSourceManager *self, ZigClangSourceLocation Loc) { @@ -1811,3 +1819,13 @@ struct ZigClangQualType ZigClangFunctionProtoType_getParamType(const struct ZigC auto casted = reinterpret_cast(self); return bitcast(casted->getParamType(index)); } + +ZigClangCompoundStmt_const_body_iterator ZigClangCompoundStmt_body_begin(const struct ZigClangCompoundStmt *self) { + auto casted = reinterpret_cast(self); + return bitcast(casted->body_begin()); +} + +ZigClangCompoundStmt_const_body_iterator ZigClangCompoundStmt_body_end(const struct ZigClangCompoundStmt *self) { + auto casted = reinterpret_cast(self); + return bitcast(casted->body_end()); +} diff --git a/src/zig_clang.h b/src/zig_clang.h index 8e0d2f9f98..fd74536b28 100644 --- a/src/zig_clang.h +++ b/src/zig_clang.h @@ -102,6 +102,8 @@ struct ZigClangVarDecl; struct ZigClangWhileStmt; struct ZigClangFunctionType; +typedef struct ZigClangStmt *const * ZigClangCompoundStmt_const_body_iterator; + enum ZigClangBO { ZigClangBO_PtrMemD, ZigClangBO_PtrMemI, @@ -820,4 +822,9 @@ ZIG_EXTERN_C struct ZigClangQualType ZigClangFunctionType_getReturnType(const st ZIG_EXTERN_C bool ZigClangFunctionProtoType_isVariadic(const struct ZigClangFunctionProtoType *self); ZIG_EXTERN_C unsigned ZigClangFunctionProtoType_getNumParams(const struct ZigClangFunctionProtoType *self); ZIG_EXTERN_C struct ZigClangQualType ZigClangFunctionProtoType_getParamType(const struct ZigClangFunctionProtoType *self, unsigned i); + + +ZIG_EXTERN_C ZigClangCompoundStmt_const_body_iterator ZigClangCompoundStmt_body_begin(const struct ZigClangCompoundStmt *self); +ZIG_EXTERN_C ZigClangCompoundStmt_const_body_iterator ZigClangCompoundStmt_body_end(const struct ZigClangCompoundStmt *self); + #endif diff --git a/test/translate_c.zig b/test/translate_c.zig index c2dfbb2860..6a2d2ef1d9 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -11,6 +11,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub extern fn bar() c_int; ); + cases.add_both("simple function definition", + \\void foo(void) {}; + , + \\pub export fn foo() void {} + ); + /////////////// Cases that pass for only stage2 //////////////// // (none)