| author | |
| committer | |
| log | 5f4c3e6557b6ffd654fad5ef3928e5f21db56a50 |
| tree | 4824cd96b2218221b6d1071d0f6901caf1774a12 |
| parent | dbb5da14f4b2fafb5000b55dd5cb44f1ddd215f1 |
| signature |
See #19646 files changed, 210 insertions(+), 49 deletions(-)
src-self-hosted/clang.zig+15-11| ... | ... | @@ -12,7 +12,7 @@ pub const struct_ZigClangCStyleCastExpr = @OpaqueType(); |
| 12 | 12 | pub const struct_ZigClangCallExpr = @OpaqueType(); |
| 13 | 13 | pub const struct_ZigClangCaseStmt = @OpaqueType(); |
| 14 | 14 | pub const struct_ZigClangCompoundAssignOperator = @OpaqueType(); |
| 15 | pub const struct_ZigClangCompoundStmt = @OpaqueType(); | |
| 15 | pub const ZigClangCompoundStmt = @OpaqueType(); | |
| 16 | 16 | pub const struct_ZigClangConditionalOperator = @OpaqueType(); |
| 17 | 17 | pub const struct_ZigClangConstantArrayType = @OpaqueType(); |
| 18 | 18 | pub const struct_ZigClangContinueStmt = @OpaqueType(); |
| ... | ... | @@ -33,7 +33,7 @@ pub const struct_ZigClangFieldDecl = @OpaqueType(); |
| 33 | 33 | pub const struct_ZigClangFileID = @OpaqueType(); |
| 34 | 34 | pub const struct_ZigClangForStmt = @OpaqueType(); |
| 35 | 35 | pub const struct_ZigClangFullSourceLoc = @OpaqueType(); |
| 36 | pub const struct_ZigClangFunctionDecl = @OpaqueType(); | |
| 36 | pub const ZigClangFunctionDecl = @OpaqueType(); | |
| 37 | 37 | pub const struct_ZigClangFunctionProtoType = @OpaqueType(); |
| 38 | 38 | pub const struct_ZigClangIfStmt = @OpaqueType(); |
| 39 | 39 | pub const struct_ZigClangImplicitCastExpr = @OpaqueType(); |
| ... | ... | @@ -488,12 +488,12 @@ pub extern fn ZigClangQualType_isRestrictQualified(arg0: struct_ZigClangQualType |
| 488 | 488 | pub extern fn ZigClangType_getTypeClass(self: ?*const struct_ZigClangType) ZigClangTypeClass; |
| 489 | 489 | pub extern fn ZigClangType_isVoidType(self: ?*const struct_ZigClangType) bool; |
| 490 | 490 | pub extern fn ZigClangType_getTypeClassName(self: *const struct_ZigClangType) [*]const u8; |
| 491 | pub extern fn ZigClangStmt_getBeginLoc(self: ?*const struct_ZigClangStmt) struct_ZigClangSourceLocation; | |
| 491 | pub extern fn ZigClangStmt_getBeginLoc(self: *const struct_ZigClangStmt) struct_ZigClangSourceLocation; | |
| 492 | 492 | pub extern fn ZigClangStmt_getStmtClass(self: ?*const struct_ZigClangStmt) ZigClangStmtClass; |
| 493 | 493 | pub extern fn ZigClangStmt_classof_Expr(self: ?*const struct_ZigClangStmt) bool; |
| 494 | 494 | pub extern fn ZigClangExpr_getStmtClass(self: ?*const struct_ZigClangExpr) ZigClangStmtClass; |
| 495 | 495 | pub extern fn ZigClangExpr_getType(self: ?*const struct_ZigClangExpr) struct_ZigClangQualType; |
| 496 | pub extern fn ZigClangExpr_getBeginLoc(self: ?*const struct_ZigClangExpr) struct_ZigClangSourceLocation; | |
| 496 | pub extern fn ZigClangExpr_getBeginLoc(self: *const struct_ZigClangExpr) struct_ZigClangSourceLocation; | |
| 497 | 497 | pub extern fn ZigClangAPValue_getKind(self: ?*const struct_ZigClangAPValue) ZigClangAPValueKind; |
| 498 | 498 | pub extern fn ZigClangAPValue_getInt(self: ?*const struct_ZigClangAPValue) ?*const struct_ZigClangAPSInt; |
| 499 | 499 | 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_ |
| 510 | 510 | pub extern fn ZigClangAPValueLValueBase_dyn_cast_Expr(self: struct_ZigClangAPValueLValueBase) ?*const struct_ZigClangExpr; |
| 511 | 511 | pub extern fn ZigClangASTUnit_delete(arg0: ?*struct_ZigClangASTUnit) void; |
| 512 | 512 | |
| 513 | pub extern fn ZigClangFunctionDecl_getType(self: *const struct_ZigClangFunctionDecl) struct_ZigClangQualType; | |
| 514 | pub extern fn ZigClangFunctionDecl_getLocation(self: *const struct_ZigClangFunctionDecl) struct_ZigClangSourceLocation; | |
| 515 | pub extern fn ZigClangFunctionDecl_hasBody(self: *const struct_ZigClangFunctionDecl) bool; | |
| 516 | pub extern fn ZigClangFunctionDecl_getStorageClass(self: *const struct_ZigClangFunctionDecl) ZigClangStorageClass; | |
| 517 | pub extern fn ZigClangFunctionDecl_getParamDecl(self: *const struct_ZigClangFunctionDecl, i: c_uint) *const struct_ZigClangParmVarDecl; | |
| 513 | pub extern fn ZigClangFunctionDecl_getType(self: *const ZigClangFunctionDecl) struct_ZigClangQualType; | |
| 514 | pub extern fn ZigClangFunctionDecl_getLocation(self: *const ZigClangFunctionDecl) struct_ZigClangSourceLocation; | |
| 515 | pub extern fn ZigClangFunctionDecl_hasBody(self: *const ZigClangFunctionDecl) bool; | |
| 516 | pub extern fn ZigClangFunctionDecl_getStorageClass(self: *const ZigClangFunctionDecl) ZigClangStorageClass; | |
| 517 | pub extern fn ZigClangFunctionDecl_getParamDecl(self: *const ZigClangFunctionDecl, i: c_uint) *const struct_ZigClangParmVarDecl; | |
| 518 | pub extern fn ZigClangFunctionDecl_getBody(self: *const ZigClangFunctionDecl) *const struct_ZigClangStmt; | |
| 518 | 519 | |
| 519 | 520 | pub extern fn ZigClangBuiltinType_getKind(self: *const struct_ZigClangBuiltinType) ZigClangBuiltinTypeKind; |
| 520 | 521 | |
| ... | ... | @@ -543,7 +544,6 @@ pub const ZigClangCStyleCastExpr = struct_ZigClangCStyleCastExpr; |
| 543 | 544 | pub const ZigClangCallExpr = struct_ZigClangCallExpr; |
| 544 | 545 | pub const ZigClangCaseStmt = struct_ZigClangCaseStmt; |
| 545 | 546 | pub const ZigClangCompoundAssignOperator = struct_ZigClangCompoundAssignOperator; |
| 546 | pub const ZigClangCompoundStmt = struct_ZigClangCompoundStmt; | |
| 547 | 547 | pub const ZigClangConditionalOperator = struct_ZigClangConditionalOperator; |
| 548 | 548 | pub const ZigClangConstantArrayType = struct_ZigClangConstantArrayType; |
| 549 | 549 | pub const ZigClangContinueStmt = struct_ZigClangContinueStmt; |
| ... | ... | @@ -564,7 +564,6 @@ pub const ZigClangFieldDecl = struct_ZigClangFieldDecl; |
| 564 | 564 | pub const ZigClangFileID = struct_ZigClangFileID; |
| 565 | 565 | pub const ZigClangForStmt = struct_ZigClangForStmt; |
| 566 | 566 | pub const ZigClangFullSourceLoc = struct_ZigClangFullSourceLoc; |
| 567 | pub const ZigClangFunctionDecl = struct_ZigClangFunctionDecl; | |
| 568 | 567 | pub const ZigClangFunctionProtoType = struct_ZigClangFunctionProtoType; |
| 569 | 568 | pub const ZigClangIfStmt = struct_ZigClangIfStmt; |
| 570 | 569 | pub const ZigClangImplicitCastExpr = struct_ZigClangImplicitCastExpr; |
| ... | ... | @@ -860,3 +859,8 @@ pub const ZigClangStorageClass = extern enum { |
| 860 | 859 | Auto, |
| 861 | 860 | Register, |
| 862 | 861 | }; |
| 862 | ||
| 863 | pub const ZigClangCompoundStmt_const_body_iterator = [*c]const *struct_ZigClangStmt; | |
| 864 | ||
| 865 | pub extern fn ZigClangCompoundStmt_body_begin(self: *const ZigClangCompoundStmt) ZigClangCompoundStmt_const_body_iterator; | |
| 866 | pub 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 | 3 | |
| 4 | 4 | const std = @import("std"); |
| 5 | 5 | const builtin = @import("builtin"); |
| 6 | const assert = std.debug.assert; | |
| 6 | 7 | const ast = std.zig.ast; |
| 7 | 8 | const Token = std.zig.Token; |
| 8 | 9 | use @import("clang.zig"); |
| ... | ... | @@ -21,6 +22,10 @@ pub const Error = error{ |
| 21 | 22 | OutOfMemory, |
| 22 | 23 | UnsupportedType, |
| 23 | 24 | }; |
| 25 | pub const TransError = error{ | |
| 26 | OutOfMemory, | |
| 27 | UnsupportedTranslation, | |
| 28 | }; | |
| 24 | 29 | |
| 25 | 30 | const DeclTable = std.HashMap(usize, void, addrHash, addrEql); |
| 26 | 31 | |
| ... | ... | @@ -61,6 +66,27 @@ const Scope = struct { |
| 61 | 66 | |
| 62 | 67 | const Block = struct { |
| 63 | 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 | }; |
| 65 | 91 | |
| 66 | 92 | const Root = struct { |
| ... | ... | @@ -72,6 +98,12 @@ const Scope = struct { |
| 72 | 98 | }; |
| 73 | 99 | }; |
| 74 | 100 | |
| 101 | const TransResult = struct { | |
| 102 | node: *ast.Node, | |
| 103 | node_scope: *Scope, | |
| 104 | child_scope: *Scope, | |
| 105 | }; | |
| 106 | ||
| 75 | 107 | const Context = struct { |
| 76 | 108 | tree: *ast.Tree, |
| 77 | 109 | source_buffer: *std.Buffer, |
| ... | ... | @@ -170,6 +202,14 @@ pub fn translate( |
| 170 | 202 | |
| 171 | 203 | _ = try appendToken(&context, .Eof, ""); |
| 172 | 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 | 213 | return tree; |
| 174 | 214 | } |
| 175 | 215 | |
| ... | ... | @@ -213,29 +253,107 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { |
| 213 | 253 | const fn_decl_loc = ZigClangFunctionDecl_getLocation(fn_decl); |
| 214 | 254 | const fn_qt = ZigClangFunctionDecl_getType(fn_decl); |
| 215 | 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 | 263 | const proto_node = switch (ZigClangType_getTypeClass(fn_type)) { |
| 217 | .FunctionProto => transFnProto( | |
| 218 | rp, | |
| 219 | @ptrCast(*const ZigClangFunctionProtoType, fn_type), | |
| 220 | fn_decl_loc, | |
| 221 | fn_decl, | |
| 222 | fn_name, | |
| 223 | ) catch |err| switch (err) { | |
| 224 | error.UnsupportedType => { | |
| 225 | return failDecl(c, fn_decl_loc, fn_name, "unable to resolve prototype of function"); | |
| 226 | }, | |
| 227 | else => return err, | |
| 264 | .FunctionProto => blk: { | |
| 265 | const fn_proto_type = @ptrCast(*const ZigClangFunctionProtoType, fn_type); | |
| 266 | break :blk transFnProto(rp, fn_proto_type, fn_decl_loc, decl_ctx) catch |err| switch (err) { | |
| 267 | error.UnsupportedType => { | |
| 268 | return failDecl(c, fn_decl_loc, fn_name, "unable to resolve prototype of function"); | |
| 269 | }, | |
| 270 | error.OutOfMemory => return error.OutOfMemory, | |
| 271 | }; | |
| 228 | 272 | }, |
| 229 | 273 | .FunctionNoProto => return failDecl(c, fn_decl_loc, fn_name, "TODO support functions with no prototype"), |
| 230 | 274 | else => unreachable, |
| 231 | 275 | }; |
| 232 | 276 | |
| 233 | if (!ZigClangFunctionDecl_hasBody(fn_decl)) { | |
| 277 | if (!decl_ctx.has_body) { | |
| 234 | 278 | const semi_tok = try appendToken(c, .Semicolon, ";"); |
| 235 | 279 | return addTopLevelDecl(c, fn_name, &proto_node.base); |
| 236 | 280 | } |
| 237 | 281 | |
| 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 | ||
| 294 | const ResultUsed = enum { | |
| 295 | used, | |
| 296 | unused, | |
| 297 | }; | |
| 298 | ||
| 299 | const LRValue = enum { | |
| 300 | l_value, | |
| 301 | r_value, | |
| 302 | }; | |
| 303 | ||
| 304 | fn 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 | ||
| 326 | fn 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 | ||
| 347 | fn 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 | } |
| 240 | 358 | |
| 241 | 359 | 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 |
| 299 | 417 | }, |
| 300 | 418 | .FunctionProto => { |
| 301 | 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 | 421 | return &fn_proto.base; |
| 304 | 422 | }, |
| 305 | 423 | else => { |
| ... | ... | @@ -309,12 +427,18 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour |
| 309 | 427 | } |
| 310 | 428 | } |
| 311 | 429 | |
| 430 | const FnDeclContext = struct { | |
| 431 | fn_name: []const u8, | |
| 432 | has_body: bool, | |
| 433 | storage_class: ZigClangStorageClass, | |
| 434 | scope: **Scope, | |
| 435 | }; | |
| 436 | ||
| 312 | 437 | fn transFnProto( |
| 313 | 438 | rp: RestorePoint, |
| 314 | 439 | fn_proto_ty: *const ZigClangFunctionProtoType, |
| 315 | 440 | source_loc: ZigClangSourceLocation, |
| 316 | opt_fn_decl: ?*const ZigClangFunctionDecl, | |
| 317 | fn_name: ?[]const u8, | |
| 441 | fn_decl_context: ?FnDeclContext, | |
| 318 | 442 | ) !*ast.Node.FnProto { |
| 319 | 443 | const fn_ty = @ptrCast(*const ZigClangFunctionType, fn_proto_ty); |
| 320 | 444 | const cc = switch (ZigClangFunctionType_getCallConv(fn_ty)) { |
| ... | ... | @@ -351,13 +475,11 @@ fn transFnProto( |
| 351 | 475 | const pub_tok = try appendToken(rp.c, .Keyword_pub, "pub"); |
| 352 | 476 | const cc_tok = if (cc == .Stdcall) try appendToken(rp.c, .Keyword_stdcallcc, "stdcallcc") else null; |
| 353 | 477 | const is_export = exp: { |
| 354 | const fn_decl = opt_fn_decl orelse break :exp false; | |
| 355 | const has_body = ZigClangFunctionDecl_hasBody(fn_decl); | |
| 356 | const storage_class = ZigClangFunctionDecl_getStorageClass(fn_decl); | |
| 357 | break :exp switch (storage_class) { | |
| 478 | const decl_ctx = fn_decl_context orelse break :exp false; | |
| 479 | break :exp switch (decl_ctx.storage_class) { | |
| 358 | 480 | .None => switch (rp.c.mode) { |
| 359 | 481 | .import => false, |
| 360 | .translate => has_body, | |
| 482 | .translate => decl_ctx.has_body, | |
| 361 | 483 | }, |
| 362 | 484 | .Extern, .Static => false, |
| 363 | 485 | .PrivateExtern => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported storage class: private extern"), |
| ... | ... | @@ -372,7 +494,7 @@ fn transFnProto( |
| 372 | 494 | else |
| 373 | 495 | null; |
| 374 | 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 | 498 | const lparen_tok = try appendToken(rp.c, .LParen, "("); |
| 377 | 499 | const var_args_tok = if (is_var_args) try appendToken(rp.c, .Ellipsis3, "...") else null; |
| 378 | 500 | const rparen_tok = try appendToken(rp.c, .RParen, ")"); |
| ... | ... | @@ -390,7 +512,7 @@ fn transFnProto( |
| 390 | 512 | try emitWarning(rp.c, source_loc, "unsupported function proto return type"); |
| 391 | 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 | 552 | } |
| 431 | 553 | |
| 432 | 554 | fn 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 | } |
| 435 | 557 | |
| 436 | 558 | fn failDecl(c: *Context, loc: ZigClangSourceLocation, name: []const u8, comptime format: []const u8, args: ...) !void { |
| 437 | 559 | // const name = @compileError(msg); |
| 438 | 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 | 562 | const eq_tok = try appendToken(c, .Equal, "="); |
| 441 | 563 | const builtin_tok = try appendToken(c, .Builtin, "@compileError"); |
| 442 | 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 | 566 | const rparen_tok = try appendToken(c, .RParen, ")"); |
| 445 | 567 | const semi_tok = try appendToken(c, .Semicolon, ";"); |
| 446 | 568 | |
| ... | ... | @@ -480,16 +602,20 @@ fn failDecl(c: *Context, loc: ZigClangSourceLocation, name: []const u8, comptime |
| 480 | 602 | try c.tree.root_node.decls.push(&var_decl_node.base); |
| 481 | 603 | } |
| 482 | 604 | |
| 483 | fn appendToken(c: *Context, token_id: Token.Id, comptime format: []const u8, args: ...) !ast.TokenIndex { | |
| 605 | fn appendToken(c: *Context, token_id: Token.Id, bytes: []const u8) !ast.TokenIndex { | |
| 606 | return appendTokenFmt(c, token_id, "{}", bytes); | |
| 607 | } | |
| 608 | ||
| 609 | fn appendTokenFmt(c: *Context, token_id: Token.Id, comptime format: []const u8, args: ...) !ast.TokenIndex { | |
| 484 | 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 | 612 | return context.source_buffer.append(bytes); |
| 487 | 613 | } |
| 488 | 614 | }; |
| 489 | 615 | const start_index = c.source_buffer.len(); |
| 490 | 616 | errdefer c.source_buffer.shrink(start_index); |
| 491 | 617 | |
| 492 | try std.fmt.format(c, Error, S.callback, format, args); | |
| 618 | try std.fmt.format(c, error{OutOfMemory}, S.callback, format, args); | |
| 493 | 619 | const end_index = c.source_buffer.len(); |
| 494 | 620 | const token_index = c.tree.tokens.len; |
| 495 | 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 | 632 | } |
| 507 | 633 | |
| 508 | 634 | fn 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 | 636 | const identifier = try c.a().create(ast.Node.Identifier); |
| 511 | 637 | identifier.* = ast.Node.Identifier{ |
| 512 | 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 | 1277 | return trans_type(c, ZigClangQualType_getTypePtr(qt), source_loc); |
| 1278 | 1278 | } |
| 1279 | 1279 | |
| 1280 | static int trans_compound_stmt_inline(Context *c, TransScope *scope, const clang::CompoundStmt *stmt, | |
| 1280 | static int trans_compound_stmt_inline(Context *c, TransScope *scope, const ZigClangCompoundStmt *stmt, | |
| 1281 | 1281 | AstNode *block_node, TransScope **out_node_scope) |
| 1282 | 1282 | { |
| 1283 | 1283 | assert(block_node->type == NodeTypeBlock); |
| 1284 | for (clang::CompoundStmt::const_body_iterator it = stmt->body_begin(), end_it = stmt->body_end(); | |
| 1285 | it != end_it; ++it) | |
| 1284 | for (ZigClangCompoundStmt_const_body_iterator it = ZigClangCompoundStmt_body_begin(stmt), | |
| 1285 | end_it = ZigClangCompoundStmt_body_end(stmt); it != end_it; ++it) | |
| 1286 | 1286 | { |
| 1287 | 1287 | AstNode *child_node; |
| 1288 | scope = trans_stmt(c, scope, bitcast(*it), &child_node); | |
| 1288 | scope = trans_stmt(c, scope, *it, &child_node); | |
| 1289 | 1289 | if (scope == nullptr) |
| 1290 | 1290 | return ErrorUnexpected; |
| 1291 | 1291 | if (child_node != nullptr) |
| ... | ... | @@ -1297,7 +1297,7 @@ static int trans_compound_stmt_inline(Context *c, TransScope *scope, const clang |
| 1297 | 1297 | return ErrorNone; |
| 1298 | 1298 | } |
| 1299 | 1299 | |
| 1300 | static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const clang::CompoundStmt *stmt, | |
| 1300 | static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const ZigClangCompoundStmt *stmt, | |
| 1301 | 1301 | TransScope **out_node_scope) |
| 1302 | 1302 | { |
| 1303 | 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 | 1309 | static AstNode *trans_stmt_expr(Context *c, ResultUsed result_used, TransScope *scope, |
| 1310 | 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 | 1313 | if (block == nullptr) |
| 1314 | 1314 | return block; |
| 1315 | 1315 | assert(block->type == NodeTypeBlock); |
| ... | ... | @@ -3220,7 +3220,7 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const cl |
| 3220 | 3220 | AstNode *body_node; |
| 3221 | 3221 | const ZigClangStmt *body_stmt = bitcast(stmt->getBody()); |
| 3222 | 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 | 3224 | block_scope->node, nullptr)) |
| 3225 | 3225 | { |
| 3226 | 3226 | return nullptr; |
| ... | ... | @@ -3399,7 +3399,7 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const ZigClangStmt *s |
| 3399 | 3399 | trans_return_stmt(c, scope, (const clang::ReturnStmt *)stmt)); |
| 3400 | 3400 | case ZigClangStmt_CompoundStmtClass: |
| 3401 | 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 | 3403 | case ZigClangStmt_IntegerLiteralClass: |
| 3404 | 3404 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3405 | 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 | 1292 | return dest; |
| 1293 | 1293 | } |
| 1294 | 1294 | |
| 1295 | static_assert(sizeof(ZigClangCompoundStmt_const_body_iterator) == sizeof(clang::CompoundStmt::const_body_iterator), ""); | |
| 1296 | static 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 | ||
| 1295 | 1303 | ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const ZigClangSourceManager *self, |
| 1296 | 1304 | ZigClangSourceLocation Loc) |
| 1297 | 1305 | { |
| ... | ... | @@ -1811,3 +1819,13 @@ struct ZigClangQualType ZigClangFunctionProtoType_getParamType(const struct ZigC |
| 1811 | 1819 | auto casted = reinterpret_cast<const clang::FunctionProtoType *>(self); |
| 1812 | 1820 | return bitcast(casted->getParamType(index)); |
| 1813 | 1821 | } |
| 1822 | ||
| 1823 | ZigClangCompoundStmt_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 | ||
| 1828 | ZigClangCompoundStmt_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 | 102 | struct ZigClangWhileStmt; |
| 103 | 103 | struct ZigClangFunctionType; |
| 104 | 104 | |
| 105 | typedef struct ZigClangStmt *const * ZigClangCompoundStmt_const_body_iterator; | |
| 106 | ||
| 105 | 107 | enum ZigClangBO { |
| 106 | 108 | ZigClangBO_PtrMemD, |
| 107 | 109 | ZigClangBO_PtrMemI, |
| ... | ... | @@ -820,4 +822,9 @@ ZIG_EXTERN_C struct ZigClangQualType ZigClangFunctionType_getReturnType(const st |
| 820 | 822 | ZIG_EXTERN_C bool ZigClangFunctionProtoType_isVariadic(const struct ZigClangFunctionProtoType *self); |
| 821 | 823 | ZIG_EXTERN_C unsigned ZigClangFunctionProtoType_getNumParams(const struct ZigClangFunctionProtoType *self); |
| 822 | 824 | ZIG_EXTERN_C struct ZigClangQualType ZigClangFunctionProtoType_getParamType(const struct ZigClangFunctionProtoType *self, unsigned i); |
| 825 | ||
| 826 | ||
| 827 | ZIG_EXTERN_C ZigClangCompoundStmt_const_body_iterator ZigClangCompoundStmt_body_begin(const struct ZigClangCompoundStmt *self); | |
| 828 | ZIG_EXTERN_C ZigClangCompoundStmt_const_body_iterator ZigClangCompoundStmt_body_end(const struct ZigClangCompoundStmt *self); | |
| 829 | ||
| 823 | 830 | #endif |
test/translate_c.zig+6| ... | ... | @@ -11,6 +11,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 11 | 11 | \\pub extern fn bar() c_int; |
| 12 | 12 | ); |
| 13 | 13 | |
| 14 | cases.add_both("simple function definition", | |
| 15 | \\void foo(void) {}; | |
| 16 | , | |
| 17 | \\pub export fn foo() void {} | |
| 18 | ); | |
| 19 | ||
| 14 | 20 | /////////////// Cases that pass for only stage2 //////////////// |
| 15 | 21 | // (none) |
| 16 | 22 |