authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-05-10 23:35:46-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-05-10 23:35:46-04:00
log5f4c3e6557b6ffd654fad5ef3928e5f21db56a50
tree4824cd96b2218221b6d1071d0f6901caf1774a12
parentdbb5da14f4b2fafb5000b55dd5cb44f1ddd215f1
signaturelock-open Commit is signed but in an unrecognized format.

stage2 translate-c: simple function definitions

See #1964

6 files changed, 210 insertions(+), 49 deletions(-)

src-self-hosted/clang.zig+15-11
...@@ -12,7 +12,7 @@ pub const struct_ZigClangCStyleCastExpr = @OpaqueType();...@@ -12,7 +12,7 @@ pub const struct_ZigClangCStyleCastExpr = @OpaqueType();
12pub const struct_ZigClangCallExpr = @OpaqueType();12pub const struct_ZigClangCallExpr = @OpaqueType();
13pub const struct_ZigClangCaseStmt = @OpaqueType();13pub const struct_ZigClangCaseStmt = @OpaqueType();
14pub const struct_ZigClangCompoundAssignOperator = @OpaqueType();14pub const struct_ZigClangCompoundAssignOperator = @OpaqueType();
15pub const struct_ZigClangCompoundStmt = @OpaqueType();15pub const ZigClangCompoundStmt = @OpaqueType();
16pub const struct_ZigClangConditionalOperator = @OpaqueType();16pub const struct_ZigClangConditionalOperator = @OpaqueType();
17pub const struct_ZigClangConstantArrayType = @OpaqueType();17pub const struct_ZigClangConstantArrayType = @OpaqueType();
18pub const struct_ZigClangContinueStmt = @OpaqueType();18pub const struct_ZigClangContinueStmt = @OpaqueType();
...@@ -33,7 +33,7 @@ pub const struct_ZigClangFieldDecl = @OpaqueType();...@@ -33,7 +33,7 @@ pub const struct_ZigClangFieldDecl = @OpaqueType();
33pub const struct_ZigClangFileID = @OpaqueType();33pub const struct_ZigClangFileID = @OpaqueType();
34pub const struct_ZigClangForStmt = @OpaqueType();34pub const struct_ZigClangForStmt = @OpaqueType();
35pub const struct_ZigClangFullSourceLoc = @OpaqueType();35pub const struct_ZigClangFullSourceLoc = @OpaqueType();
36pub const struct_ZigClangFunctionDecl = @OpaqueType();36pub const ZigClangFunctionDecl = @OpaqueType();
37pub const struct_ZigClangFunctionProtoType = @OpaqueType();37pub const struct_ZigClangFunctionProtoType = @OpaqueType();
38pub const struct_ZigClangIfStmt = @OpaqueType();38pub const struct_ZigClangIfStmt = @OpaqueType();
39pub const struct_ZigClangImplicitCastExpr = @OpaqueType();39pub const struct_ZigClangImplicitCastExpr = @OpaqueType();
...@@ -488,12 +488,12 @@ pub extern fn ZigClangQualType_isRestrictQualified(arg0: struct_ZigClangQualType...@@ -488,12 +488,12 @@ pub extern fn ZigClangQualType_isRestrictQualified(arg0: struct_ZigClangQualType
488pub extern fn ZigClangType_getTypeClass(self: ?*const struct_ZigClangType) ZigClangTypeClass;488pub extern fn ZigClangType_getTypeClass(self: ?*const struct_ZigClangType) ZigClangTypeClass;
489pub extern fn ZigClangType_isVoidType(self: ?*const struct_ZigClangType) bool;489pub extern fn ZigClangType_isVoidType(self: ?*const struct_ZigClangType) bool;
490pub extern fn ZigClangType_getTypeClassName(self: *const struct_ZigClangType) [*]const u8;490pub extern fn ZigClangType_getTypeClassName(self: *const struct_ZigClangType) [*]const u8;
491pub extern fn ZigClangStmt_getBeginLoc(self: ?*const struct_ZigClangStmt) struct_ZigClangSourceLocation;491pub extern fn ZigClangStmt_getBeginLoc(self: *const struct_ZigClangStmt) struct_ZigClangSourceLocation;
492pub extern fn ZigClangStmt_getStmtClass(self: ?*const struct_ZigClangStmt) ZigClangStmtClass;492pub extern fn ZigClangStmt_getStmtClass(self: ?*const struct_ZigClangStmt) ZigClangStmtClass;
493pub extern fn ZigClangStmt_classof_Expr(self: ?*const struct_ZigClangStmt) bool;493pub extern fn ZigClangStmt_classof_Expr(self: ?*const struct_ZigClangStmt) bool;
494pub extern fn ZigClangExpr_getStmtClass(self: ?*const struct_ZigClangExpr) ZigClangStmtClass;494pub extern fn ZigClangExpr_getStmtClass(self: ?*const struct_ZigClangExpr) ZigClangStmtClass;
495pub extern fn ZigClangExpr_getType(self: ?*const struct_ZigClangExpr) struct_ZigClangQualType;495pub extern fn ZigClangExpr_getType(self: ?*const struct_ZigClangExpr) struct_ZigClangQualType;
496pub extern fn ZigClangExpr_getBeginLoc(self: ?*const struct_ZigClangExpr) struct_ZigClangSourceLocation;496pub extern fn ZigClangExpr_getBeginLoc(self: *const struct_ZigClangExpr) struct_ZigClangSourceLocation;
497pub extern fn ZigClangAPValue_getKind(self: ?*const struct_ZigClangAPValue) ZigClangAPValueKind;497pub extern fn ZigClangAPValue_getKind(self: ?*const struct_ZigClangAPValue) ZigClangAPValueKind;
498pub extern fn ZigClangAPValue_getInt(self: ?*const struct_ZigClangAPValue) ?*const struct_ZigClangAPSInt;498pub extern fn ZigClangAPValue_getInt(self: ?*const struct_ZigClangAPValue) ?*const struct_ZigClangAPSInt;
499pub extern fn ZigClangAPValue_getArrayInitializedElts(self: ?*const struct_ZigClangAPValue) c_uint;499pub extern fn ZigClangAPValue_getArrayInitializedElts(self: ?*const struct_ZigClangAPValue) c_uint;
...@@ -510,11 +510,12 @@ pub extern fn ZigClangAPSInt_getNumWords(self: ?*const struct_ZigClangAPSInt) c_...@@ -510,11 +510,12 @@ pub extern fn ZigClangAPSInt_getNumWords(self: ?*const struct_ZigClangAPSInt) c_
510pub extern fn ZigClangAPValueLValueBase_dyn_cast_Expr(self: struct_ZigClangAPValueLValueBase) ?*const struct_ZigClangExpr;510pub extern fn ZigClangAPValueLValueBase_dyn_cast_Expr(self: struct_ZigClangAPValueLValueBase) ?*const struct_ZigClangExpr;
511pub extern fn ZigClangASTUnit_delete(arg0: ?*struct_ZigClangASTUnit) void;511pub extern fn ZigClangASTUnit_delete(arg0: ?*struct_ZigClangASTUnit) void;
512512
513pub extern fn ZigClangFunctionDecl_getType(self: *const struct_ZigClangFunctionDecl) struct_ZigClangQualType;513pub extern fn ZigClangFunctionDecl_getType(self: *const ZigClangFunctionDecl) struct_ZigClangQualType;
514pub extern fn ZigClangFunctionDecl_getLocation(self: *const struct_ZigClangFunctionDecl) struct_ZigClangSourceLocation;514pub extern fn ZigClangFunctionDecl_getLocation(self: *const ZigClangFunctionDecl) struct_ZigClangSourceLocation;
515pub extern fn ZigClangFunctionDecl_hasBody(self: *const struct_ZigClangFunctionDecl) bool;515pub extern fn ZigClangFunctionDecl_hasBody(self: *const ZigClangFunctionDecl) bool;
516pub extern fn ZigClangFunctionDecl_getStorageClass(self: *const struct_ZigClangFunctionDecl) ZigClangStorageClass;516pub extern fn ZigClangFunctionDecl_getStorageClass(self: *const ZigClangFunctionDecl) ZigClangStorageClass;
517pub extern fn ZigClangFunctionDecl_getParamDecl(self: *const struct_ZigClangFunctionDecl, i: c_uint) *const struct_ZigClangParmVarDecl;517pub extern fn ZigClangFunctionDecl_getParamDecl(self: *const ZigClangFunctionDecl, i: c_uint) *const struct_ZigClangParmVarDecl;
518pub extern fn ZigClangFunctionDecl_getBody(self: *const ZigClangFunctionDecl) *const struct_ZigClangStmt;
518519
519pub extern fn ZigClangBuiltinType_getKind(self: *const struct_ZigClangBuiltinType) ZigClangBuiltinTypeKind;520pub extern fn ZigClangBuiltinType_getKind(self: *const struct_ZigClangBuiltinType) ZigClangBuiltinTypeKind;
520521
...@@ -543,7 +544,6 @@ pub const ZigClangCStyleCastExpr = struct_ZigClangCStyleCastExpr;...@@ -543,7 +544,6 @@ pub const ZigClangCStyleCastExpr = struct_ZigClangCStyleCastExpr;
543pub const ZigClangCallExpr = struct_ZigClangCallExpr;544pub const ZigClangCallExpr = struct_ZigClangCallExpr;
544pub const ZigClangCaseStmt = struct_ZigClangCaseStmt;545pub const ZigClangCaseStmt = struct_ZigClangCaseStmt;
545pub const ZigClangCompoundAssignOperator = struct_ZigClangCompoundAssignOperator;546pub const ZigClangCompoundAssignOperator = struct_ZigClangCompoundAssignOperator;
546pub const ZigClangCompoundStmt = struct_ZigClangCompoundStmt;
547pub const ZigClangConditionalOperator = struct_ZigClangConditionalOperator;547pub const ZigClangConditionalOperator = struct_ZigClangConditionalOperator;
548pub const ZigClangConstantArrayType = struct_ZigClangConstantArrayType;548pub const ZigClangConstantArrayType = struct_ZigClangConstantArrayType;
549pub const ZigClangContinueStmt = struct_ZigClangContinueStmt;549pub const ZigClangContinueStmt = struct_ZigClangContinueStmt;
...@@ -564,7 +564,6 @@ pub const ZigClangFieldDecl = struct_ZigClangFieldDecl;...@@ -564,7 +564,6 @@ pub const ZigClangFieldDecl = struct_ZigClangFieldDecl;
564pub const ZigClangFileID = struct_ZigClangFileID;564pub const ZigClangFileID = struct_ZigClangFileID;
565pub const ZigClangForStmt = struct_ZigClangForStmt;565pub const ZigClangForStmt = struct_ZigClangForStmt;
566pub const ZigClangFullSourceLoc = struct_ZigClangFullSourceLoc;566pub const ZigClangFullSourceLoc = struct_ZigClangFullSourceLoc;
567pub const ZigClangFunctionDecl = struct_ZigClangFunctionDecl;
568pub const ZigClangFunctionProtoType = struct_ZigClangFunctionProtoType;567pub const ZigClangFunctionProtoType = struct_ZigClangFunctionProtoType;
569pub const ZigClangIfStmt = struct_ZigClangIfStmt;568pub const ZigClangIfStmt = struct_ZigClangIfStmt;
570pub const ZigClangImplicitCastExpr = struct_ZigClangImplicitCastExpr;569pub const ZigClangImplicitCastExpr = struct_ZigClangImplicitCastExpr;
...@@ -860,3 +859,8 @@ pub const ZigClangStorageClass = extern enum {...@@ -860,3 +859,8 @@ pub const ZigClangStorageClass = extern enum {
860 Auto,859 Auto,
861 Register,860 Register,
862};861};
862
863pub const ZigClangCompoundStmt_const_body_iterator = [*c]const *struct_ZigClangStmt;
864
865pub extern fn ZigClangCompoundStmt_body_begin(self: *const ZigClangCompoundStmt) ZigClangCompoundStmt_const_body_iterator;
866pub extern fn ZigClangCompoundStmt_body_end(self: *const ZigClangCompoundStmt) ZigClangCompoundStmt_const_body_iterator;
src-self-hosted/translate_c.zig+156-30
...@@ -3,6 +3,7 @@...@@ -3,6 +3,7 @@
33
4const std = @import("std");4const std = @import("std");
5const builtin = @import("builtin");5const builtin = @import("builtin");
6const assert = std.debug.assert;
6const ast = std.zig.ast;7const ast = std.zig.ast;
7const Token = std.zig.Token;8const Token = std.zig.Token;
8use @import("clang.zig");9use @import("clang.zig");
...@@ -21,6 +22,10 @@ pub const Error = error{...@@ -21,6 +22,10 @@ pub const Error = error{
21 OutOfMemory,22 OutOfMemory,
22 UnsupportedType,23 UnsupportedType,
23};24};
25pub const TransError = error{
26 OutOfMemory,
27 UnsupportedTranslation,
28};
2429
25const DeclTable = std.HashMap(usize, void, addrHash, addrEql);30const DeclTable = std.HashMap(usize, void, addrHash, addrEql);
2631
...@@ -61,6 +66,27 @@ const Scope = struct {...@@ -61,6 +66,27 @@ const Scope = struct {
6166
62 const Block = struct {67 const Block = struct {
63 base: Scope,68 base: Scope,
69 block_node: *ast.Node.Block,
70
71 /// Don't forget to set rbrace token later
72 fn create(c: *Context, parent: *Scope, lbrace_tok: ast.TokenIndex) !*Block {
73 const block = try c.a().create(Block);
74 block.* = Block{
75 .base = Scope{
76 .id = Id.Block,
77 .parent = parent,
78 },
79 .block_node = try c.a().create(ast.Node.Block),
80 };
81 block.block_node.* = ast.Node.Block{
82 .base = ast.Node{ .id = ast.Node.Id.Block },
83 .label = null,
84 .lbrace = lbrace_tok,
85 .statements = ast.Node.Block.StatementList.init(c.a()),
86 .rbrace = undefined,
87 };
88 return block;
89 }
64 };90 };
6591
66 const Root = struct {92 const Root = struct {
...@@ -72,6 +98,12 @@ const Scope = struct {...@@ -72,6 +98,12 @@ const Scope = struct {
72 };98 };
73};99};
74100
101const TransResult = struct {
102 node: *ast.Node,
103 node_scope: *Scope,
104 child_scope: *Scope,
105};
106
75const Context = struct {107const Context = struct {
76 tree: *ast.Tree,108 tree: *ast.Tree,
77 source_buffer: *std.Buffer,109 source_buffer: *std.Buffer,
...@@ -170,6 +202,14 @@ pub fn translate(...@@ -170,6 +202,14 @@ pub fn translate(
170202
171 _ = try appendToken(&context, .Eof, "");203 _ = try appendToken(&context, .Eof, "");
172 tree.source = source_buffer.toOwnedSlice();204 tree.source = source_buffer.toOwnedSlice();
205 if (false) {
206 std.debug.warn("debug source:\n{}\n==EOF==\ntokens:\n", tree.source);
207 var i: usize = 0;
208 while (i < tree.tokens.len) : (i += 1) {
209 const token = tree.tokens.at(i);
210 std.debug.warn("{}\n", token);
211 }
212 }
173 return tree;213 return tree;
174}214}
175215
...@@ -213,29 +253,107 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {...@@ -213,29 +253,107 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
213 const fn_decl_loc = ZigClangFunctionDecl_getLocation(fn_decl);253 const fn_decl_loc = ZigClangFunctionDecl_getLocation(fn_decl);
214 const fn_qt = ZigClangFunctionDecl_getType(fn_decl);254 const fn_qt = ZigClangFunctionDecl_getType(fn_decl);
215 const fn_type = ZigClangQualType_getTypePtr(fn_qt);255 const fn_type = ZigClangQualType_getTypePtr(fn_qt);
256 var scope = &c.global_scope.base;
257 const decl_ctx = FnDeclContext{
258 .fn_name = fn_name,
259 .has_body = ZigClangFunctionDecl_hasBody(fn_decl),
260 .storage_class = ZigClangFunctionDecl_getStorageClass(fn_decl),
261 .scope = &scope,
262 };
216 const proto_node = switch (ZigClangType_getTypeClass(fn_type)) {263 const proto_node = switch (ZigClangType_getTypeClass(fn_type)) {
217 .FunctionProto => transFnProto(264 .FunctionProto => blk: {
218 rp,265 const fn_proto_type = @ptrCast(*const ZigClangFunctionProtoType, fn_type);
219 @ptrCast(*const ZigClangFunctionProtoType, fn_type),266 break :blk transFnProto(rp, fn_proto_type, fn_decl_loc, decl_ctx) catch |err| switch (err) {
220 fn_decl_loc,267 error.UnsupportedType => {
221 fn_decl,268 return failDecl(c, fn_decl_loc, fn_name, "unable to resolve prototype of function");
222 fn_name,269 },
223 ) catch |err| switch (err) {270 error.OutOfMemory => return error.OutOfMemory,
224 error.UnsupportedType => {271 };
225 return failDecl(c, fn_decl_loc, fn_name, "unable to resolve prototype of function");
226 },
227 else => return err,
228 },272 },
229 .FunctionNoProto => return failDecl(c, fn_decl_loc, fn_name, "TODO support functions with no prototype"),273 .FunctionNoProto => return failDecl(c, fn_decl_loc, fn_name, "TODO support functions with no prototype"),
230 else => unreachable,274 else => unreachable,
231 };275 };
232276
233 if (!ZigClangFunctionDecl_hasBody(fn_decl)) {277 if (!decl_ctx.has_body) {
234 const semi_tok = try appendToken(c, .Semicolon, ";");278 const semi_tok = try appendToken(c, .Semicolon, ";");
235 return addTopLevelDecl(c, fn_name, &proto_node.base);279 return addTopLevelDecl(c, fn_name, &proto_node.base);
236 }280 }
237281
238 try emitWarning(c, fn_decl_loc, "TODO implement function body translation");282 // actual function definition with body
283 const body_stmt = ZigClangFunctionDecl_getBody(fn_decl);
284 const result = transStmt(rp, scope, body_stmt, .unused, .r_value) catch |err| switch (err) {
285 error.OutOfMemory => return error.OutOfMemory,
286 error.UnsupportedTranslation => return failDecl(c, fn_decl_loc, fn_name, "unable to translate function"),
287 };
288 assert(result.node.id == ast.Node.Id.Block);
289 proto_node.body_node = result.node;
290
291 return addTopLevelDecl(c, fn_name, &proto_node.base);
292}
293
294const ResultUsed = enum {
295 used,
296 unused,
297};
298
299const LRValue = enum {
300 l_value,
301 r_value,
302};
303
304fn transStmt(
305 rp: RestorePoint,
306 scope: *Scope,
307 stmt: *const ZigClangStmt,
308 result_used: ResultUsed,
309 lrvalue: LRValue,
310) !TransResult {
311 const sc = ZigClangStmt_getStmtClass(stmt);
312 switch (sc) {
313 .CompoundStmtClass => return transCompoundStmt(rp, scope, @ptrCast(*const ZigClangCompoundStmt, stmt)),
314 else => {
315 return revertAndWarn(
316 rp,
317 error.UnsupportedTranslation,
318 ZigClangStmt_getBeginLoc(stmt),
319 "TODO implement translation of stmt class {}",
320 @tagName(sc),
321 );
322 },
323 }
324}
325
326fn transCompoundStmtInline(
327 rp: RestorePoint,
328 parent_scope: *Scope,
329 stmt: *const ZigClangCompoundStmt,
330 block_node: *ast.Node.Block,
331) TransError!TransResult {
332 var it = ZigClangCompoundStmt_body_begin(stmt);
333 const end_it = ZigClangCompoundStmt_body_end(stmt);
334 var scope = parent_scope;
335 while (it != end_it) : (it += 1) {
336 const result = try transStmt(rp, scope, it.*, .unused, .r_value);
337 scope = result.child_scope;
338 try block_node.statements.push(result.node);
339 }
340 return TransResult{
341 .node = &block_node.base,
342 .child_scope = scope,
343 .node_scope = scope,
344 };
345}
346
347fn transCompoundStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundStmt) !TransResult {
348 const lbrace_tok = try appendToken(rp.c, .LBrace, "{");
349 const block_scope = try Scope.Block.create(rp.c, scope, lbrace_tok);
350 const inline_result = try transCompoundStmtInline(rp, &block_scope.base, stmt, block_scope.block_node);
351 block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}");
352 return TransResult{
353 .node = &block_scope.block_node.base,
354 .node_scope = inline_result.node_scope,
355 .child_scope = inline_result.child_scope,
356 };
239}357}
240358
241fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: *ast.Node) !void {359fn 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...@@ -299,7 +417,7 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
299 },417 },
300 .FunctionProto => {418 .FunctionProto => {
301 const fn_proto_ty = @ptrCast(*const ZigClangFunctionProtoType, ty);419 const fn_proto_ty = @ptrCast(*const ZigClangFunctionProtoType, ty);
302 const fn_proto = try transFnProto(rp, fn_proto_ty, source_loc, null, null);420 const fn_proto = try transFnProto(rp, fn_proto_ty, source_loc, null);
303 return &fn_proto.base;421 return &fn_proto.base;
304 },422 },
305 else => {423 else => {
...@@ -309,12 +427,18 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour...@@ -309,12 +427,18 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
309 }427 }
310}428}
311429
430const FnDeclContext = struct {
431 fn_name: []const u8,
432 has_body: bool,
433 storage_class: ZigClangStorageClass,
434 scope: **Scope,
435};
436
312fn transFnProto(437fn transFnProto(
313 rp: RestorePoint,438 rp: RestorePoint,
314 fn_proto_ty: *const ZigClangFunctionProtoType,439 fn_proto_ty: *const ZigClangFunctionProtoType,
315 source_loc: ZigClangSourceLocation,440 source_loc: ZigClangSourceLocation,
316 opt_fn_decl: ?*const ZigClangFunctionDecl,441 fn_decl_context: ?FnDeclContext,
317 fn_name: ?[]const u8,
318) !*ast.Node.FnProto {442) !*ast.Node.FnProto {
319 const fn_ty = @ptrCast(*const ZigClangFunctionType, fn_proto_ty);443 const fn_ty = @ptrCast(*const ZigClangFunctionType, fn_proto_ty);
320 const cc = switch (ZigClangFunctionType_getCallConv(fn_ty)) {444 const cc = switch (ZigClangFunctionType_getCallConv(fn_ty)) {
...@@ -351,13 +475,11 @@ fn transFnProto(...@@ -351,13 +475,11 @@ fn transFnProto(
351 const pub_tok = try appendToken(rp.c, .Keyword_pub, "pub");475 const pub_tok = try appendToken(rp.c, .Keyword_pub, "pub");
352 const cc_tok = if (cc == .Stdcall) try appendToken(rp.c, .Keyword_stdcallcc, "stdcallcc") else null;476 const cc_tok = if (cc == .Stdcall) try appendToken(rp.c, .Keyword_stdcallcc, "stdcallcc") else null;
353 const is_export = exp: {477 const is_export = exp: {
354 const fn_decl = opt_fn_decl orelse break :exp false;478 const decl_ctx = fn_decl_context orelse break :exp false;
355 const has_body = ZigClangFunctionDecl_hasBody(fn_decl);479 break :exp switch (decl_ctx.storage_class) {
356 const storage_class = ZigClangFunctionDecl_getStorageClass(fn_decl);
357 break :exp switch (storage_class) {
358 .None => switch (rp.c.mode) {480 .None => switch (rp.c.mode) {
359 .import => false,481 .import => false,
360 .translate => has_body,482 .translate => decl_ctx.has_body,
361 },483 },
362 .Extern, .Static => false,484 .Extern, .Static => false,
363 .PrivateExtern => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported storage class: private extern"),485 .PrivateExtern => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported storage class: private extern"),
...@@ -372,7 +494,7 @@ fn transFnProto(...@@ -372,7 +494,7 @@ fn transFnProto(
372 else494 else
373 null;495 null;
374 const fn_tok = try appendToken(rp.c, .Keyword_fn, "fn");496 const fn_tok = try appendToken(rp.c, .Keyword_fn, "fn");
375 const name_tok = if (fn_name) |n| try appendToken(rp.c, .Identifier, "{}", n) else null;497 const name_tok = if (fn_decl_context) |ctx| try appendToken(rp.c, .Identifier, ctx.fn_name) else null;
376 const lparen_tok = try appendToken(rp.c, .LParen, "(");498 const lparen_tok = try appendToken(rp.c, .LParen, "(");
377 const var_args_tok = if (is_var_args) try appendToken(rp.c, .Ellipsis3, "...") else null;499 const var_args_tok = if (is_var_args) try appendToken(rp.c, .Ellipsis3, "...") else null;
378 const rparen_tok = try appendToken(rp.c, .RParen, ")");500 const rparen_tok = try appendToken(rp.c, .RParen, ")");
...@@ -390,7 +512,7 @@ fn transFnProto(...@@ -390,7 +512,7 @@ fn transFnProto(
390 try emitWarning(rp.c, source_loc, "unsupported function proto return type");512 try emitWarning(rp.c, source_loc, "unsupported function proto return type");
391 return err;513 return err;
392 },514 },
393 else => return err,515 error.OutOfMemory => return error.OutOfMemory,
394 };516 };
395 }517 }
396 }518 }
...@@ -430,17 +552,17 @@ fn revertAndWarn(...@@ -430,17 +552,17 @@ fn revertAndWarn(
430}552}
431553
432fn emitWarning(c: *Context, loc: ZigClangSourceLocation, comptime format: []const u8, args: ...) !void {554fn emitWarning(c: *Context, loc: ZigClangSourceLocation, comptime format: []const u8, args: ...) !void {
433 _ = try appendToken(c, .LineComment, "// {}: warning: " ++ format, c.locStr(loc), args);555 _ = try appendTokenFmt(c, .LineComment, "// {}: warning: " ++ format, c.locStr(loc), args);
434}556}
435557
436fn failDecl(c: *Context, loc: ZigClangSourceLocation, name: []const u8, comptime format: []const u8, args: ...) !void {558fn failDecl(c: *Context, loc: ZigClangSourceLocation, name: []const u8, comptime format: []const u8, args: ...) !void {
437 // const name = @compileError(msg);559 // const name = @compileError(msg);
438 const const_tok = try appendToken(c, .Keyword_const, "const");560 const const_tok = try appendToken(c, .Keyword_const, "const");
439 const name_tok = try appendToken(c, .Identifier, "{}", name);561 const name_tok = try appendToken(c, .Identifier, name);
440 const eq_tok = try appendToken(c, .Equal, "=");562 const eq_tok = try appendToken(c, .Equal, "=");
441 const builtin_tok = try appendToken(c, .Builtin, "@compileError");563 const builtin_tok = try appendToken(c, .Builtin, "@compileError");
442 const lparen_tok = try appendToken(c, .LParen, "(");564 const lparen_tok = try appendToken(c, .LParen, "(");
443 const msg_tok = try appendToken(c, .StringLiteral, "\"" ++ format ++ "\"", args);565 const msg_tok = try appendTokenFmt(c, .StringLiteral, "\"" ++ format ++ "\"", args);
444 const rparen_tok = try appendToken(c, .RParen, ")");566 const rparen_tok = try appendToken(c, .RParen, ")");
445 const semi_tok = try appendToken(c, .Semicolon, ";");567 const semi_tok = try appendToken(c, .Semicolon, ";");
446568
...@@ -480,16 +602,20 @@ fn failDecl(c: *Context, loc: ZigClangSourceLocation, name: []const u8, comptime...@@ -480,16 +602,20 @@ fn failDecl(c: *Context, loc: ZigClangSourceLocation, name: []const u8, comptime
480 try c.tree.root_node.decls.push(&var_decl_node.base);602 try c.tree.root_node.decls.push(&var_decl_node.base);
481}603}
482604
483fn appendToken(c: *Context, token_id: Token.Id, comptime format: []const u8, args: ...) !ast.TokenIndex {605fn appendToken(c: *Context, token_id: Token.Id, bytes: []const u8) !ast.TokenIndex {
606 return appendTokenFmt(c, token_id, "{}", bytes);
607}
608
609fn appendTokenFmt(c: *Context, token_id: Token.Id, comptime format: []const u8, args: ...) !ast.TokenIndex {
484 const S = struct {610 const S = struct {
485 fn callback(context: *Context, bytes: []const u8) Error!void {611 fn callback(context: *Context, bytes: []const u8) error{OutOfMemory}!void {
486 return context.source_buffer.append(bytes);612 return context.source_buffer.append(bytes);
487 }613 }
488 };614 };
489 const start_index = c.source_buffer.len();615 const start_index = c.source_buffer.len();
490 errdefer c.source_buffer.shrink(start_index);616 errdefer c.source_buffer.shrink(start_index);
491617
492 try std.fmt.format(c, Error, S.callback, format, args);618 try std.fmt.format(c, error{OutOfMemory}, S.callback, format, args);
493 const end_index = c.source_buffer.len();619 const end_index = c.source_buffer.len();
494 const token_index = c.tree.tokens.len;620 const token_index = c.tree.tokens.len;
495 const new_token = try c.tree.tokens.addOne();621 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...@@ -506,7 +632,7 @@ fn appendToken(c: *Context, token_id: Token.Id, comptime format: []const u8, arg
506}632}
507633
508fn appendIdentifier(c: *Context, name: []const u8) !*ast.Node {634fn appendIdentifier(c: *Context, name: []const u8) !*ast.Node {
509 const token_index = try appendToken(c, .Identifier, "{}", name);635 const token_index = try appendToken(c, .Identifier, name);
510 const identifier = try c.a().create(ast.Node.Identifier);636 const identifier = try c.a().create(ast.Node.Identifier);
511 identifier.* = ast.Node.Identifier{637 identifier.* = ast.Node.Identifier{
512 .base = ast.Node{ .id = ast.Node.Id.Identifier },638 .base = ast.Node{ .id = ast.Node.Id.Identifier },
src/translate_c.cpp+8-8
...@@ -1277,15 +1277,15 @@ static AstNode *trans_qual_type(Context *c, ZigClangQualType qt, ZigClangSourceL...@@ -1277,15 +1277,15 @@ static AstNode *trans_qual_type(Context *c, ZigClangQualType qt, ZigClangSourceL
1277 return trans_type(c, ZigClangQualType_getTypePtr(qt), source_loc);1277 return trans_type(c, ZigClangQualType_getTypePtr(qt), source_loc);
1278}1278}
12791279
1280static int trans_compound_stmt_inline(Context *c, TransScope *scope, const clang::CompoundStmt *stmt,1280static int trans_compound_stmt_inline(Context *c, TransScope *scope, const ZigClangCompoundStmt *stmt,
1281 AstNode *block_node, TransScope **out_node_scope)1281 AstNode *block_node, TransScope **out_node_scope)
1282{1282{
1283 assert(block_node->type == NodeTypeBlock);1283 assert(block_node->type == NodeTypeBlock);
1284 for (clang::CompoundStmt::const_body_iterator it = stmt->body_begin(), end_it = stmt->body_end();1284 for (ZigClangCompoundStmt_const_body_iterator it = ZigClangCompoundStmt_body_begin(stmt),
1285 it != end_it; ++it)1285 end_it = ZigClangCompoundStmt_body_end(stmt); it != end_it; ++it)
1286 {1286 {
1287 AstNode *child_node;1287 AstNode *child_node;
1288 scope = trans_stmt(c, scope, bitcast(*it), &child_node);1288 scope = trans_stmt(c, scope, *it, &child_node);
1289 if (scope == nullptr)1289 if (scope == nullptr)
1290 return ErrorUnexpected;1290 return ErrorUnexpected;
1291 if (child_node != nullptr)1291 if (child_node != nullptr)
...@@ -1297,7 +1297,7 @@ static int trans_compound_stmt_inline(Context *c, TransScope *scope, const clang...@@ -1297,7 +1297,7 @@ static int trans_compound_stmt_inline(Context *c, TransScope *scope, const clang
1297 return ErrorNone;1297 return ErrorNone;
1298}1298}
12991299
1300static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const clang::CompoundStmt *stmt,1300static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const ZigClangCompoundStmt *stmt,
1301 TransScope **out_node_scope)1301 TransScope **out_node_scope)
1302{1302{
1303 TransScopeBlock *child_scope_block = trans_scope_block_create(c, scope);1303 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::...@@ -1309,7 +1309,7 @@ static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const clang::
1309static AstNode *trans_stmt_expr(Context *c, ResultUsed result_used, TransScope *scope,1309static AstNode *trans_stmt_expr(Context *c, ResultUsed result_used, TransScope *scope,
1310 const clang::StmtExpr *stmt, TransScope **out_node_scope)1310 const clang::StmtExpr *stmt, TransScope **out_node_scope)
1311{1311{
1312 AstNode *block = trans_compound_stmt(c, scope, stmt->getSubStmt(), out_node_scope);1312 AstNode *block = trans_compound_stmt(c, scope, (const ZigClangCompoundStmt *)stmt->getSubStmt(), out_node_scope);
1313 if (block == nullptr)1313 if (block == nullptr)
1314 return block;1314 return block;
1315 assert(block->type == NodeTypeBlock);1315 assert(block->type == NodeTypeBlock);
...@@ -3220,7 +3220,7 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const cl...@@ -3220,7 +3220,7 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const cl
3220 AstNode *body_node;3220 AstNode *body_node;
3221 const ZigClangStmt *body_stmt = bitcast(stmt->getBody());3221 const ZigClangStmt *body_stmt = bitcast(stmt->getBody());
3222 if (ZigClangStmt_getStmtClass(body_stmt) == ZigClangStmt_CompoundStmtClass) {3222 if (ZigClangStmt_getStmtClass(body_stmt) == ZigClangStmt_CompoundStmtClass) {
3223 if (trans_compound_stmt_inline(c, &switch_scope->base, (const clang::CompoundStmt *)body_stmt,3223 if (trans_compound_stmt_inline(c, &switch_scope->base, (const ZigClangCompoundStmt *)body_stmt,
3224 block_scope->node, nullptr))3224 block_scope->node, nullptr))
3225 {3225 {
3226 return nullptr;3226 return nullptr;
...@@ -3399,7 +3399,7 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const ZigClangStmt *s...@@ -3399,7 +3399,7 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const ZigClangStmt *s
3399 trans_return_stmt(c, scope, (const clang::ReturnStmt *)stmt));3399 trans_return_stmt(c, scope, (const clang::ReturnStmt *)stmt));
3400 case ZigClangStmt_CompoundStmtClass:3400 case ZigClangStmt_CompoundStmtClass:
3401 return wrap_stmt(out_node, out_child_scope, scope,3401 return wrap_stmt(out_node, out_child_scope, scope,
3402 trans_compound_stmt(c, scope, (const clang::CompoundStmt *)stmt, out_node_scope));3402 trans_compound_stmt(c, scope, (const ZigClangCompoundStmt *)stmt, out_node_scope));
3403 case ZigClangStmt_IntegerLiteralClass:3403 case ZigClangStmt_IntegerLiteralClass:
3404 return wrap_stmt(out_node, out_child_scope, scope,3404 return wrap_stmt(out_node, out_child_scope, scope,
3405 trans_integer_literal(c, result_used, (const clang::IntegerLiteral *)stmt));3405 trans_integer_literal(c, result_used, (const clang::IntegerLiteral *)stmt));
src/zig_clang.cpp+18
...@@ -1292,6 +1292,14 @@ static clang::APValue::LValueBase bitcast(ZigClangAPValueLValueBase src) {...@@ -1292,6 +1292,14 @@ static clang::APValue::LValueBase bitcast(ZigClangAPValueLValueBase src) {
1292 return dest;1292 return dest;
1293}1293}
12941294
1295static_assert(sizeof(ZigClangCompoundStmt_const_body_iterator) == sizeof(clang::CompoundStmt::const_body_iterator), "");
1296static ZigClangCompoundStmt_const_body_iterator bitcast(clang::CompoundStmt::const_body_iterator src) {
1297 ZigClangCompoundStmt_const_body_iterator dest;
1298 memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangCompoundStmt_const_body_iterator));
1299 return dest;
1300}
1301
1302
1295ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const ZigClangSourceManager *self,1303ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const ZigClangSourceManager *self,
1296 ZigClangSourceLocation Loc)1304 ZigClangSourceLocation Loc)
1297{1305{
...@@ -1811,3 +1819,13 @@ struct ZigClangQualType ZigClangFunctionProtoType_getParamType(const struct ZigC...@@ -1811,3 +1819,13 @@ struct ZigClangQualType ZigClangFunctionProtoType_getParamType(const struct ZigC
1811 auto casted = reinterpret_cast<const clang::FunctionProtoType *>(self);1819 auto casted = reinterpret_cast<const clang::FunctionProtoType *>(self);
1812 return bitcast(casted->getParamType(index));1820 return bitcast(casted->getParamType(index));
1813}1821}
1822
1823ZigClangCompoundStmt_const_body_iterator ZigClangCompoundStmt_body_begin(const struct ZigClangCompoundStmt *self) {
1824 auto casted = reinterpret_cast<const clang::CompoundStmt *>(self);
1825 return bitcast(casted->body_begin());
1826}
1827
1828ZigClangCompoundStmt_const_body_iterator ZigClangCompoundStmt_body_end(const struct ZigClangCompoundStmt *self) {
1829 auto casted = reinterpret_cast<const clang::CompoundStmt *>(self);
1830 return bitcast(casted->body_end());
1831}
src/zig_clang.h+7
...@@ -102,6 +102,8 @@ struct ZigClangVarDecl;...@@ -102,6 +102,8 @@ struct ZigClangVarDecl;
102struct ZigClangWhileStmt;102struct ZigClangWhileStmt;
103struct ZigClangFunctionType;103struct ZigClangFunctionType;
104104
105typedef struct ZigClangStmt *const * ZigClangCompoundStmt_const_body_iterator;
106
105enum ZigClangBO {107enum ZigClangBO {
106 ZigClangBO_PtrMemD,108 ZigClangBO_PtrMemD,
107 ZigClangBO_PtrMemI,109 ZigClangBO_PtrMemI,
...@@ -820,4 +822,9 @@ ZIG_EXTERN_C struct ZigClangQualType ZigClangFunctionType_getReturnType(const st...@@ -820,4 +822,9 @@ ZIG_EXTERN_C struct ZigClangQualType ZigClangFunctionType_getReturnType(const st
820ZIG_EXTERN_C bool ZigClangFunctionProtoType_isVariadic(const struct ZigClangFunctionProtoType *self);822ZIG_EXTERN_C bool ZigClangFunctionProtoType_isVariadic(const struct ZigClangFunctionProtoType *self);
821ZIG_EXTERN_C unsigned ZigClangFunctionProtoType_getNumParams(const struct ZigClangFunctionProtoType *self);823ZIG_EXTERN_C unsigned ZigClangFunctionProtoType_getNumParams(const struct ZigClangFunctionProtoType *self);
822ZIG_EXTERN_C struct ZigClangQualType ZigClangFunctionProtoType_getParamType(const struct ZigClangFunctionProtoType *self, unsigned i);824ZIG_EXTERN_C struct ZigClangQualType ZigClangFunctionProtoType_getParamType(const struct ZigClangFunctionProtoType *self, unsigned i);
825
826
827ZIG_EXTERN_C ZigClangCompoundStmt_const_body_iterator ZigClangCompoundStmt_body_begin(const struct ZigClangCompoundStmt *self);
828ZIG_EXTERN_C ZigClangCompoundStmt_const_body_iterator ZigClangCompoundStmt_body_end(const struct ZigClangCompoundStmt *self);
829
823#endif830#endif
test/translate_c.zig+6
...@@ -11,6 +11,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -11,6 +11,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
11 \\pub extern fn bar() c_int;11 \\pub extern fn bar() c_int;
12 );12 );
1313
14 cases.add_both("simple function definition",
15 \\void foo(void) {};
16 ,
17 \\pub export fn foo() void {}
18 );
19
14 /////////////// Cases that pass for only stage2 ////////////////20 /////////////// Cases that pass for only stage2 ////////////////
15 // (none)21 // (none)
1622