translate-c-2 don't shadow primitive types

This commit is contained in:
Vexu 2019-12-17 10:20:02 +02:00
parent ab6fe57462
commit 9cda93a24e
No known key found for this signature in database
GPG Key ID: 59AEB8936E16A6AC
2 changed files with 66 additions and 27 deletions

View File

@ -69,9 +69,7 @@ const Scope = struct {
label: ?[]const u8, label: ?[]const u8,
/// Don't forget to set rbrace token and block_node later /// Don't forget to set rbrace token and block_node later
fn init(c: *Context, parent: *Scope, want_label: bool) !*Block { fn init(c: *Context, parent: *Scope, label: ?[]const u8) !*Block {
// TODO removing `?[]const u8` here causes LLVM error
const label: ?[]const u8 = if (want_label) try std.fmt.allocPrint(c.a(), "blk_{}", .{c.getMangle()}) else null;
const block = try c.a().create(Block); const block = try c.a().create(Block);
block.* = .{ block.* = .{
.base = .{ .base = .{
@ -171,7 +169,7 @@ const Scope = struct {
.Condition => { .Condition => {
const cond = @fieldParentPtr(Condition, "base", scope); const cond = @fieldParentPtr(Condition, "base", scope);
// comma operator used // comma operator used
return try Block.init(c, scope, true); return try Block.init(c, scope, "blk");
}, },
else => scope = scope.parent.?, else => scope = scope.parent.?,
} }
@ -179,7 +177,7 @@ const Scope = struct {
} }
fn createAlias(scope: *Scope, c: *Context, name: []const u8) !?[]const u8 { fn createAlias(scope: *Scope, c: *Context, name: []const u8) !?[]const u8 {
if (scope.contains(name)) { if (isZigPrimitiveType(name) or scope.contains(name)) {
return try std.fmt.allocPrint(c.a(), "{}_{}", .{ name, c.getMangle() }); return try std.fmt.allocPrint(c.a(), "{}_{}", .{ name, c.getMangle() });
} }
return null; return null;
@ -452,7 +450,11 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
const scope = &c.global_scope.base; const scope = &c.global_scope.base;
const var_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, var_decl))); const var_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, var_decl)));
_ = try c.decl_table.put(@ptrToInt(var_decl), var_name);
// TODO https://github.com/ziglang/zig/issues/3756
// TODO https://github.com/ziglang/zig/issues/1802
const checked_name = if (isZigPrimitiveType(var_name)) try std.fmt.allocPrint(c.a(), "_{}", .{var_name}) else var_name;
_ = try c.decl_table.put(@ptrToInt(var_decl), checked_name);
const var_decl_loc = ZigClangVarDecl_getLocation(var_decl); const var_decl_loc = ZigClangVarDecl_getLocation(var_decl);
const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl); const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl);
@ -471,12 +473,12 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
else else
try appendToken(c, .Keyword_var, "var"); try appendToken(c, .Keyword_var, "var");
const name_tok = try appendIdentifier(c, var_name); const name_tok = try appendIdentifier(c, checked_name);
_ = try appendToken(c, .Colon, ":"); _ = try appendToken(c, .Colon, ":");
const type_node = transQualType(rp, qual_type, var_decl_loc) catch |err| switch (err) { const type_node = transQualType(rp, qual_type, var_decl_loc) catch |err| switch (err) {
error.UnsupportedType => { error.UnsupportedType => {
return failDecl(c, var_decl_loc, var_name, "unable to resolve variable type", .{}); return failDecl(c, var_decl_loc, checked_name, "unable to resolve variable type", .{});
}, },
error.OutOfMemory => |e| return e, error.OutOfMemory => |e| return e,
}; };
@ -491,14 +493,14 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
error.UnsupportedTranslation, error.UnsupportedTranslation,
error.UnsupportedType, error.UnsupportedType,
=> { => {
return failDecl(c, var_decl_loc, var_name, "unable to translate initializer", .{}); return failDecl(c, var_decl_loc, checked_name, "unable to translate initializer", .{});
}, },
error.OutOfMemory => |e| return e, error.OutOfMemory => |e| return e,
} }
else else
try transCreateNodeUndefinedLiteral(c); try transCreateNodeUndefinedLiteral(c);
} else if (storage_class != .Extern) { } else if (storage_class != .Extern) {
return failDecl(c, var_decl_loc, var_name, "non-extern variable has no initializer", .{}); return failDecl(c, var_decl_loc, checked_name, "non-extern variable has no initializer", .{});
} }
const node = try c.a().create(ast.Node.VarDecl); const node = try c.a().create(ast.Node.VarDecl);
@ -518,7 +520,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
.init_node = init_node, .init_node = init_node,
.semicolon_token = try appendToken(c, .Semicolon, ";"), .semicolon_token = try appendToken(c, .Semicolon, ";"),
}; };
return addTopLevelDecl(c, var_name, &node.base); return addTopLevelDecl(c, checked_name, &node.base);
} }
fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Error!void { fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Error!void {
@ -796,7 +798,7 @@ fn transCompoundStmtInline(
} }
fn transCompoundStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundStmt) TransError!*ast.Node { fn transCompoundStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundStmt) TransError!*ast.Node {
const block_scope = try Scope.Block.init(rp.c, scope, false); const block_scope = try Scope.Block.init(rp.c, scope, null);
block_scope.block_node = try transCreateNodeBlock(rp.c, null); block_scope.block_node = try transCreateNodeBlock(rp.c, null);
try transCompoundStmtInline(rp, &block_scope.base, stmt, block_scope.block_node); try transCompoundStmtInline(rp, &block_scope.base, stmt, block_scope.block_node);
block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}"); block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}");
@ -1316,7 +1318,7 @@ fn transForLoop(
var block = false; var block = false;
var block_scope: ?*Scope.Block = null; var block_scope: ?*Scope.Block = null;
if (ZigClangForStmt_getInit(stmt)) |init| { if (ZigClangForStmt_getInit(stmt)) |init| {
block_scope = try Scope.Block.init(rp.c, scope, false); block_scope = try Scope.Block.init(rp.c, scope, null);
block_scope.?.block_node = try transCreateNodeBlock(rp.c, null); block_scope.?.block_node = try transCreateNodeBlock(rp.c, null);
inner = &block_scope.?.base; inner = &block_scope.?.base;
_ = try transStmt(rp, inner, init, .unused, .r_value); _ = try transStmt(rp, inner, init, .unused, .r_value);
@ -1803,7 +1805,7 @@ fn transCreateNodeAssign(
// zig: break :x _tmp // zig: break :x _tmp
// zig: }) // zig: })
_ = try appendToken(rp.c, .LParen, "("); _ = try appendToken(rp.c, .LParen, "(");
const block_scope = try Scope.Block.init(rp.c, scope, true); const block_scope = try Scope.Block.init(rp.c, scope, "blk");
block_scope.block_node = try transCreateNodeBlock(rp.c, block_scope.label); block_scope.block_node = try transCreateNodeBlock(rp.c, block_scope.label);
const tmp = try std.fmt.allocPrint(rp.c.a(), "_tmp_{}", .{rp.c.getMangle()}); const tmp = try std.fmt.allocPrint(rp.c.a(), "_tmp_{}", .{rp.c.getMangle()});
@ -2732,6 +2734,33 @@ fn appendTokenFmt(c: *Context, token_id: Token.Id, comptime format: []const u8,
return token_index; return token_index;
} }
// TODO hook up with codegen
fn isZigPrimitiveType(name: []const u8) bool {
if (name.len > 1 and std.mem.startsWith(u8, name, "u") or std.mem.startsWith(u8, name, "u")) {
for (name[1..]) |c| {
switch (c) {
'0'...'9' => {},
else => return false,
}
}
return true;
}
// void is invalid in c so it doesn't need to be checked.
return std.mem.eql(u8, name, "comptime_float") or
std.mem.eql(u8, name, "comptime_int") or
std.mem.eql(u8, name, "bool") or
std.mem.eql(u8, name, "isize") or
std.mem.eql(u8, name, "usize") or
std.mem.eql(u8, name, "f16") or
std.mem.eql(u8, name, "f32") or
std.mem.eql(u8, name, "f64") or
std.mem.eql(u8, name, "f128") or
std.mem.eql(u8, name, "c_longdouble") or
std.mem.eql(u8, name, "noreturn") or
std.mem.eql(u8, name, "type") or
std.mem.eql(u8, name, "anyerror");
}
fn isValidZigIdentifier(name: []const u8) bool { fn isValidZigIdentifier(name: []const u8) bool {
for (name) |c, i| { for (name) |c, i| {
switch (c) { switch (c) {
@ -2782,27 +2811,31 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {
const begin_loc = ZigClangMacroDefinitionRecord_getSourceRange_getBegin(macro); const begin_loc = ZigClangMacroDefinitionRecord_getSourceRange_getBegin(macro);
const name = try c.str(raw_name); const name = try c.str(raw_name);
if (scope.contains(name)) {
// TODO https://github.com/ziglang/zig/issues/3756
// TODO https://github.com/ziglang/zig/issues/1802
const checked_name = if (isZigPrimitiveType(name)) try std.fmt.allocPrint(c.a(), "_{}", .{name}) else name;
if (scope.contains(checked_name)) {
continue; continue;
} }
const begin_c = ZigClangSourceManager_getCharacterData(c.source_manager, begin_loc); const begin_c = ZigClangSourceManager_getCharacterData(c.source_manager, begin_loc);
ctok.tokenizeCMacro(&tok_list, begin_c) catch |err| switch (err) { ctok.tokenizeCMacro(&tok_list, begin_c) catch |err| switch (err) {
error.OutOfMemory => |e| return e, error.OutOfMemory => |e| return e,
else => { else => {
try failDecl(c, begin_loc, name, "unable to tokenize macro definition", .{}); try failDecl(c, begin_loc, checked_name, "unable to tokenize macro definition", .{});
continue; continue;
}, },
}; };
var tok_it = tok_list.iterator(0); var tok_it = tok_list.iterator(0);
const first_tok = tok_it.next().?; const first_tok = tok_it.next().?;
assert(first_tok.id == .Identifier and std.mem.eql(u8, first_tok.bytes, name)); assert(first_tok.id == .Identifier and std.mem.eql(u8, first_tok.bytes, checked_name));
const next = tok_it.peek().?; const next = tok_it.peek().?;
switch (next.id) { switch (next.id) {
.Identifier => { .Identifier => {
// if it equals itself, ignore. for example, from stdio.h: // if it equals itself, ignore. for example, from stdio.h:
// #define stdin stdin // #define stdin stdin
if (std.mem.eql(u8, name, next.bytes)) { if (std.mem.eql(u8, checked_name, next.bytes)) {
continue; continue;
} }
}, },
@ -2819,12 +2852,12 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {
} else false; } else false;
(if (macro_fn) (if (macro_fn)
transMacroFnDefine(c, &tok_it, name, begin_loc) transMacroFnDefine(c, &tok_it, checked_name, begin_loc)
else else
transMacroDefine(c, &tok_it, name, begin_loc)) catch |err| switch (err) { transMacroDefine(c, &tok_it, checked_name, begin_loc)) catch |err| switch (err) {
error.UnsupportedTranslation, error.UnsupportedTranslation,
error.ParseError, error.ParseError,
=> try failDecl(c, begin_loc, name, "unable to translate macro", .{}), => try failDecl(c, begin_loc, checked_name, "unable to translate macro", .{}),
error.OutOfMemory => |e| return e, error.OutOfMemory => |e| return e,
}; };
}, },

View File

@ -724,10 +724,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub export fn foo(c: u8) c_int { \\pub export fn foo(c: u8) c_int {
\\ var a: c_int = undefined; \\ var a: c_int = undefined;
\\ var b: c_int = undefined; \\ var b: c_int = undefined;
\\ a = blk_1: { \\ a = blk: {
\\ const _tmp_2 = 2; \\ const _tmp_1 = 2;
\\ b = _tmp_2; \\ b = _tmp_1;
\\ break :blk_1 _tmp_2; \\ break :blk _tmp_1;
\\ }; \\ };
\\} \\}
}); });
@ -746,9 +746,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ if (2 != 0) { \\ if (2 != 0) {
\\ var a: c_int = 2; \\ var a: c_int = 2;
\\ } \\ }
\\ if ((blk_1: { \\ if ((blk: {
\\ _ = 2; \\ _ = 2;
\\ break :blk_1 5; \\ break :blk 5;
\\ }) != 0) { \\ }) != 0) {
\\ var a: c_int = 2; \\ var a: c_int = 2;
\\ } \\ }
@ -819,6 +819,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\} \\}
}); });
cases.add_2("shadowing primitive types",
\\unsigned anyerror = 2;
, &[_][]const u8{
\\pub export var _anyerror: c_uint = @as(c_uint, 2);
});
/////////////// Cases for only stage1 which are TODO items for stage2 //////////////// /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
if (builtin.os != builtin.Os.windows) { if (builtin.os != builtin.Os.windows) {