| ... | ... | @@ -69,9 +69,7 @@ const Scope = struct { |
| 69 | 69 | label: ?[]const u8, |
| 70 | 70 | |
| 71 | 71 | /// Don't forget to set rbrace token and block_node later |
| 72 | | fn init(c: *Context, parent: *Scope, want_label: bool) !*Block { |
| 73 | | // TODO removing `?[]const u8` here causes LLVM error |
| 74 | | const label: ?[]const u8 = if (want_label) try std.fmt.allocPrint(c.a(), "blk_{}", .{c.getMangle()}) else null; |
| 72 | fn init(c: *Context, parent: *Scope, label: ?[]const u8) !*Block { |
| 75 | 73 | const block = try c.a().create(Block); |
| 76 | 74 | block.* = .{ |
| 77 | 75 | .base = .{ |
| ... | ... | @@ -171,7 +169,7 @@ const Scope = struct { |
| 171 | 169 | .Condition => { |
| 172 | 170 | const cond = @fieldParentPtr(Condition, "base", scope); |
| 173 | 171 | // comma operator used |
| 174 | | return try Block.init(c, scope, true); |
| 172 | return try Block.init(c, scope, "blk"); |
| 175 | 173 | }, |
| 176 | 174 | else => scope = scope.parent.?, |
| 177 | 175 | } |
| ... | ... | @@ -179,7 +177,7 @@ const Scope = struct { |
| 179 | 177 | } |
| 180 | 178 | |
| 181 | 179 | fn createAlias(scope: *Scope, c: *Context, name: []const u8) !?[]const u8 { |
| 182 | | if (scope.contains(name)) { |
| 180 | if (isZigPrimitiveType(name) or scope.contains(name)) { |
| 183 | 181 | return try std.fmt.allocPrint(c.a(), "{}_{}", .{ name, c.getMangle() }); |
| 184 | 182 | } |
| 185 | 183 | return null; |
| ... | ... | @@ -452,7 +450,11 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { |
| 452 | 450 | |
| 453 | 451 | const scope = &c.global_scope.base; |
| 454 | 452 | const var_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, var_decl))); |
| 455 | | _ = try c.decl_table.put(@ptrToInt(var_decl), var_name); |
| 453 | |
| 454 | // TODO https://github.com/ziglang/zig/issues/3756 |
| 455 | // TODO https://github.com/ziglang/zig/issues/1802 |
| 456 | const checked_name = if (isZigPrimitiveType(var_name)) try std.fmt.allocPrint(c.a(), "_{}", .{var_name}) else var_name; |
| 457 | _ = try c.decl_table.put(@ptrToInt(var_decl), checked_name); |
| 456 | 458 | const var_decl_loc = ZigClangVarDecl_getLocation(var_decl); |
| 457 | 459 | |
| 458 | 460 | const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl); |
| ... | ... | @@ -471,12 +473,12 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { |
| 471 | 473 | else |
| 472 | 474 | try appendToken(c, .Keyword_var, "var"); |
| 473 | 475 | |
| 474 | | const name_tok = try appendIdentifier(c, var_name); |
| 476 | const name_tok = try appendIdentifier(c, checked_name); |
| 475 | 477 | |
| 476 | 478 | _ = try appendToken(c, .Colon, ":"); |
| 477 | 479 | const type_node = transQualType(rp, qual_type, var_decl_loc) catch |err| switch (err) { |
| 478 | 480 | error.UnsupportedType => { |
| 479 | | return failDecl(c, var_decl_loc, var_name, "unable to resolve variable type", .{}); |
| 481 | return failDecl(c, var_decl_loc, checked_name, "unable to resolve variable type", .{}); |
| 480 | 482 | }, |
| 481 | 483 | error.OutOfMemory => |e| return e, |
| 482 | 484 | }; |
| ... | ... | @@ -491,14 +493,14 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { |
| 491 | 493 | error.UnsupportedTranslation, |
| 492 | 494 | error.UnsupportedType, |
| 493 | 495 | => { |
| 494 | | return failDecl(c, var_decl_loc, var_name, "unable to translate initializer", .{}); |
| 496 | return failDecl(c, var_decl_loc, checked_name, "unable to translate initializer", .{}); |
| 495 | 497 | }, |
| 496 | 498 | error.OutOfMemory => |e| return e, |
| 497 | 499 | } |
| 498 | 500 | else |
| 499 | 501 | try transCreateNodeUndefinedLiteral(c); |
| 500 | 502 | } else if (storage_class != .Extern) { |
| 501 | | return failDecl(c, var_decl_loc, var_name, "non-extern variable has no initializer", .{}); |
| 503 | return failDecl(c, var_decl_loc, checked_name, "non-extern variable has no initializer", .{}); |
| 502 | 504 | } |
| 503 | 505 | |
| 504 | 506 | const node = try c.a().create(ast.Node.VarDecl); |
| ... | ... | @@ -518,7 +520,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { |
| 518 | 520 | .init_node = init_node, |
| 519 | 521 | .semicolon_token = try appendToken(c, .Semicolon, ";"), |
| 520 | 522 | }; |
| 521 | | return addTopLevelDecl(c, var_name, &node.base); |
| 523 | return addTopLevelDecl(c, checked_name, &node.base); |
| 522 | 524 | } |
| 523 | 525 | |
| 524 | 526 | fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Error!void { |
| ... | ... | @@ -796,7 +798,7 @@ fn transCompoundStmtInline( |
| 796 | 798 | } |
| 797 | 799 | |
| 798 | 800 | fn transCompoundStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundStmt) TransError!*ast.Node { |
| 799 | | const block_scope = try Scope.Block.init(rp.c, scope, false); |
| 801 | const block_scope = try Scope.Block.init(rp.c, scope, null); |
| 800 | 802 | block_scope.block_node = try transCreateNodeBlock(rp.c, null); |
| 801 | 803 | try transCompoundStmtInline(rp, &block_scope.base, stmt, block_scope.block_node); |
| 802 | 804 | block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}"); |
| ... | ... | @@ -1316,7 +1318,7 @@ fn transForLoop( |
| 1316 | 1318 | var block = false; |
| 1317 | 1319 | var block_scope: ?*Scope.Block = null; |
| 1318 | 1320 | if (ZigClangForStmt_getInit(stmt)) |init| { |
| 1319 | | block_scope = try Scope.Block.init(rp.c, scope, false); |
| 1321 | block_scope = try Scope.Block.init(rp.c, scope, null); |
| 1320 | 1322 | block_scope.?.block_node = try transCreateNodeBlock(rp.c, null); |
| 1321 | 1323 | inner = &block_scope.?.base; |
| 1322 | 1324 | _ = try transStmt(rp, inner, init, .unused, .r_value); |
| ... | ... | @@ -1803,7 +1805,7 @@ fn transCreateNodeAssign( |
| 1803 | 1805 | // zig: break :x _tmp |
| 1804 | 1806 | // zig: }) |
| 1805 | 1807 | _ = try appendToken(rp.c, .LParen, "("); |
| 1806 | | const block_scope = try Scope.Block.init(rp.c, scope, true); |
| 1808 | const block_scope = try Scope.Block.init(rp.c, scope, "blk"); |
| 1807 | 1809 | block_scope.block_node = try transCreateNodeBlock(rp.c, block_scope.label); |
| 1808 | 1810 | const tmp = try std.fmt.allocPrint(rp.c.a(), "_tmp_{}", .{rp.c.getMangle()}); |
| 1809 | 1811 | |
| ... | ... | @@ -2732,6 +2734,33 @@ fn appendTokenFmt(c: *Context, token_id: Token.Id, comptime format: []const u8, |
| 2732 | 2734 | return token_index; |
| 2733 | 2735 | } |
| 2734 | 2736 | |
| 2737 | // TODO hook up with codegen |
| 2738 | fn isZigPrimitiveType(name: []const u8) bool { |
| 2739 | if (name.len > 1 and std.mem.startsWith(u8, name, "u") or std.mem.startsWith(u8, name, "u")) { |
| 2740 | for (name[1..]) |c| { |
| 2741 | switch (c) { |
| 2742 | '0'...'9' => {}, |
| 2743 | else => return false, |
| 2744 | } |
| 2745 | } |
| 2746 | return true; |
| 2747 | } |
| 2748 | // void is invalid in c so it doesn't need to be checked. |
| 2749 | return std.mem.eql(u8, name, "comptime_float") or |
| 2750 | std.mem.eql(u8, name, "comptime_int") or |
| 2751 | std.mem.eql(u8, name, "bool") or |
| 2752 | std.mem.eql(u8, name, "isize") or |
| 2753 | std.mem.eql(u8, name, "usize") or |
| 2754 | std.mem.eql(u8, name, "f16") or |
| 2755 | std.mem.eql(u8, name, "f32") or |
| 2756 | std.mem.eql(u8, name, "f64") or |
| 2757 | std.mem.eql(u8, name, "f128") or |
| 2758 | std.mem.eql(u8, name, "c_longdouble") or |
| 2759 | std.mem.eql(u8, name, "noreturn") or |
| 2760 | std.mem.eql(u8, name, "type") or |
| 2761 | std.mem.eql(u8, name, "anyerror"); |
| 2762 | } |
| 2763 | |
| 2735 | 2764 | fn isValidZigIdentifier(name: []const u8) bool { |
| 2736 | 2765 | for (name) |c, i| { |
| 2737 | 2766 | switch (c) { |
| ... | ... | @@ -2782,27 +2811,31 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void { |
| 2782 | 2811 | const begin_loc = ZigClangMacroDefinitionRecord_getSourceRange_getBegin(macro); |
| 2783 | 2812 | |
| 2784 | 2813 | const name = try c.str(raw_name); |
| 2785 | | if (scope.contains(name)) { |
| 2814 | |
| 2815 | // TODO https://github.com/ziglang/zig/issues/3756 |
| 2816 | // TODO https://github.com/ziglang/zig/issues/1802 |
| 2817 | const checked_name = if (isZigPrimitiveType(name)) try std.fmt.allocPrint(c.a(), "_{}", .{name}) else name; |
| 2818 | if (scope.contains(checked_name)) { |
| 2786 | 2819 | continue; |
| 2787 | 2820 | } |
| 2788 | 2821 | const begin_c = ZigClangSourceManager_getCharacterData(c.source_manager, begin_loc); |
| 2789 | 2822 | ctok.tokenizeCMacro(&tok_list, begin_c) catch |err| switch (err) { |
| 2790 | 2823 | error.OutOfMemory => |e| return e, |
| 2791 | 2824 | else => { |
| 2792 | | try failDecl(c, begin_loc, name, "unable to tokenize macro definition", .{}); |
| 2825 | try failDecl(c, begin_loc, checked_name, "unable to tokenize macro definition", .{}); |
| 2793 | 2826 | continue; |
| 2794 | 2827 | }, |
| 2795 | 2828 | }; |
| 2796 | 2829 | |
| 2797 | 2830 | var tok_it = tok_list.iterator(0); |
| 2798 | 2831 | const first_tok = tok_it.next().?; |
| 2799 | | assert(first_tok.id == .Identifier and std.mem.eql(u8, first_tok.bytes, name)); |
| 2832 | assert(first_tok.id == .Identifier and std.mem.eql(u8, first_tok.bytes, checked_name)); |
| 2800 | 2833 | const next = tok_it.peek().?; |
| 2801 | 2834 | switch (next.id) { |
| 2802 | 2835 | .Identifier => { |
| 2803 | 2836 | // if it equals itself, ignore. for example, from stdio.h: |
| 2804 | 2837 | // #define stdin stdin |
| 2805 | | if (std.mem.eql(u8, name, next.bytes)) { |
| 2838 | if (std.mem.eql(u8, checked_name, next.bytes)) { |
| 2806 | 2839 | continue; |
| 2807 | 2840 | } |
| 2808 | 2841 | }, |
| ... | ... | @@ -2819,12 +2852,12 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void { |
| 2819 | 2852 | } else false; |
| 2820 | 2853 | |
| 2821 | 2854 | (if (macro_fn) |
| 2822 | | transMacroFnDefine(c, &tok_it, name, begin_loc) |
| 2855 | transMacroFnDefine(c, &tok_it, checked_name, begin_loc) |
| 2823 | 2856 | else |
| 2824 | | transMacroDefine(c, &tok_it, name, begin_loc)) catch |err| switch (err) { |
| 2857 | transMacroDefine(c, &tok_it, checked_name, begin_loc)) catch |err| switch (err) { |
| 2825 | 2858 | error.UnsupportedTranslation, |
| 2826 | 2859 | error.ParseError, |
| 2827 | | => try failDecl(c, begin_loc, name, "unable to translate macro", .{}), |
| 2860 | => try failDecl(c, begin_loc, checked_name, "unable to translate macro", .{}), |
| 2828 | 2861 | error.OutOfMemory => |e| return e, |
| 2829 | 2862 | }; |
| 2830 | 2863 | }, |