authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-17 14:11:49+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-17 14:11:49+02:00
loge2974759dd62e15f04e1aeb8babee65e6ffb3413
treec2bce83baef92d278bb6953baad647ae7e76c901
parent9a826ccbe0b10046e5dd7c482e9e87912c0fa95c
signature Commit is signed but in an unrecognized format.

translate-c: demote untranslatable declarations to externs


3 files changed, 35 insertions(+), 13 deletions(-)

src/translate_c.zig+27-11
...@@ -508,7 +508,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {...@@ -508,7 +508,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {
508 decl_ctx.has_body = false;508 decl_ctx.has_body = false;
509 decl_ctx.storage_class = .Extern;509 decl_ctx.storage_class = .Extern;
510 decl_ctx.is_export = false;510 decl_ctx.is_export = false;
511 try warn(c, &c.global_scope.base, fn_decl_loc, "TODO unable to translate variadic function, demoted to declaration", .{});511 try warn(c, &c.global_scope.base, fn_decl_loc, "TODO unable to translate variadic function, demoted to extern", .{});
512 }512 }
513 break :blk transFnProto(c, fn_decl, fn_proto_type, fn_decl_loc, decl_ctx, true) catch |err| switch (err) {513 break :blk transFnProto(c, fn_decl, fn_proto_type, fn_decl_loc, decl_ctx, true) catch |err| switch (err) {
514 error.UnsupportedType => {514 error.UnsupportedType => {
...@@ -543,8 +543,12 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {...@@ -543,8 +543,12 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {
543543
544 var param_id: c_uint = 0;544 var param_id: c_uint = 0;
545 for (proto_node.data.params) |*param, i| {545 for (proto_node.data.params) |*param, i| {
546 const param_name = param.name orelse546 const param_name = param.name orelse {
547 return failDecl(c, fn_decl_loc, fn_name, "function {s} parameter has no name", .{fn_name});547 proto_node.data.is_extern = true;
548 proto_node.data.is_export = false;
549 try warn(c, &c.global_scope.base, fn_decl_loc, "function {s} parameter has no name, demoted to extern", .{fn_name});
550 return addTopLevelDecl(c, fn_name, Node.initPayload(&proto_node.base));
551 };
548552
549 const c_param = fn_decl.getParamDecl(param_id);553 const c_param = fn_decl.getParamDecl(param_id);
550 const qual_type = c_param.getOriginalType();554 const qual_type = c_param.getOriginalType();
...@@ -570,7 +574,12 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {...@@ -570,7 +574,12 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {
570 error.OutOfMemory => |e| return e,574 error.OutOfMemory => |e| return e,
571 error.UnsupportedTranslation,575 error.UnsupportedTranslation,
572 error.UnsupportedType,576 error.UnsupportedType,
573 => return failDecl(c, fn_decl_loc, fn_name, "unable to translate function", .{}),577 => {
578 proto_node.data.is_extern = true;
579 proto_node.data.is_export = false;
580 try warn(c, &c.global_scope.base, fn_decl_loc, "unable to translate function, demoted to extern", .{});
581 return addTopLevelDecl(c, fn_name, Node.initPayload(&proto_node.base));
582 },
574 };583 };
575 // add return statement if the function didn't have one584 // add return statement if the function didn't have one
576 blk: {585 blk: {
...@@ -598,7 +607,12 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {...@@ -598,7 +607,12 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {
598 error.OutOfMemory => |e| return e,607 error.OutOfMemory => |e| return e,
599 error.UnsupportedTranslation,608 error.UnsupportedTranslation,
600 error.UnsupportedType,609 error.UnsupportedType,
601 => return failDecl(c, fn_decl_loc, fn_name, "unable to create a return value for function", .{}),610 => {
611 proto_node.data.is_extern = true;
612 proto_node.data.is_export = false;
613 try warn(c, &c.global_scope.base, fn_decl_loc, "unable to create a return value for function, demoted to extern", .{});
614 return addTopLevelDecl(c, fn_name, Node.initPayload(&proto_node.base));
615 },
602 };616 };
603 const ret = try Tag.@"return".create(c.arena, rhs);617 const ret = try Tag.@"return".create(c.arena, rhs);
604 try block_scope.statements.append(ret);618 try block_scope.statements.append(ret);
...@@ -641,8 +655,8 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co...@@ -641,8 +655,8 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co
641 // does the same as:655 // does the same as:
642 // extern int foo;656 // extern int foo;
643 // int foo = 2;657 // int foo = 2;
644 const is_extern = storage_class == .Extern and !has_init;658 var is_extern = storage_class == .Extern and !has_init;
645 const is_export = !is_extern and storage_class != .Static;659 var is_export = !is_extern and storage_class != .Static;
646660
647 const type_node = transQualTypeMaybeInitialized(c, qual_type, decl_init, var_decl_loc) catch |err| switch (err) {661 const type_node = transQualTypeMaybeInitialized(c, qual_type, decl_init, var_decl_loc) catch |err| switch (err) {
648 error.UnsupportedTranslation, error.UnsupportedType => {662 error.UnsupportedTranslation, error.UnsupportedType => {
...@@ -656,7 +670,7 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co...@@ -656,7 +670,7 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co
656 // If the initialization expression is not present, initialize with undefined.670 // If the initialization expression is not present, initialize with undefined.
657 // If it is an integer literal, we can skip the @as since it will be redundant671 // If it is an integer literal, we can skip the @as since it will be redundant
658 // with the variable type.672 // with the variable type.
659 if (has_init) {673 if (has_init) trans_init: {
660 if (decl_init) |expr| {674 if (decl_init) |expr| {
661 const node_or_error = if (expr.getStmtClass() == .StringLiteralClass)675 const node_or_error = if (expr.getStmtClass() == .StringLiteralClass)
662 transStringLiteralAsArray(c, scope, @ptrCast(*const clang.StringLiteral, expr), zigArraySize(c, type_node) catch 0)676 transStringLiteralAsArray(c, scope, @ptrCast(*const clang.StringLiteral, expr), zigArraySize(c, type_node) catch 0)
...@@ -666,7 +680,10 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co...@@ -666,7 +680,10 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co
666 error.UnsupportedTranslation,680 error.UnsupportedTranslation,
667 error.UnsupportedType,681 error.UnsupportedType,
668 => {682 => {
669 return failDecl(c, var_decl_loc, checked_name, "unable to translate initializer", .{});683 is_extern = true;
684 is_export = false;
685 try warn(c, scope, var_decl_loc, "unable to translate variable initializer, demoted to extern", .{});
686 break :trans_init;
670 },687 },
671 error.OutOfMemory => |e| return e,688 error.OutOfMemory => |e| return e,
672 };689 };
...@@ -1845,7 +1862,7 @@ fn literalFitsInType(c: *Context, expr: *const clang.Expr, qt: clang.QualType) b...@@ -1845,7 +1862,7 @@ fn literalFitsInType(c: *Context, expr: *const clang.Expr, qt: clang.QualType) b
1845 var width = qualTypeIntBitWidth(c, qt) catch 8;1862 var width = qualTypeIntBitWidth(c, qt) catch 8;
1846 if (width == 0) width = 8; // Byte is the smallest type.1863 if (width == 0) width = 8; // Byte is the smallest type.
1847 const is_signed = cIsSignedInteger(qt);1864 const is_signed = cIsSignedInteger(qt);
1848 const width_max_int= (@as(u64, 1) << math.lossyCast(u6, width - @boolToInt(is_signed))) - 1;1865 const width_max_int = (@as(u64, 1) << math.lossyCast(u6, width - @boolToInt(is_signed))) - 1;
18491866
1850 switch (@ptrCast(*const clang.Stmt, expr).getStmtClass()) {1867 switch (@ptrCast(*const clang.Stmt, expr).getStmtClass()) {
1851 .CharacterLiteralClass => {1868 .CharacterLiteralClass => {
...@@ -1866,7 +1883,6 @@ fn literalFitsInType(c: *Context, expr: *const clang.Expr, qt: clang.QualType) b...@@ -1866,7 +1883,6 @@ fn literalFitsInType(c: *Context, expr: *const clang.Expr, qt: clang.QualType) b
1866 },1883 },
1867 else => unreachable,1884 else => unreachable,
1868 }1885 }
1869
1870}1886}
18711887
1872fn transInitListExprRecord(1888fn transInitListExprRecord(
src/translate_c/ast.zig+6
...@@ -1866,6 +1866,12 @@ fn addSemicolonIfNeeded(c: *Context, node: Node) !void {...@@ -1866,6 +1866,12 @@ fn addSemicolonIfNeeded(c: *Context, node: Node) !void {
1866fn addSemicolonIfNotBlock(c: *Context, node: Node) !void {1866fn addSemicolonIfNotBlock(c: *Context, node: Node) !void {
1867 switch (node.tag()) {1867 switch (node.tag()) {
1868 .block, .empty_block, .block_single, => {},1868 .block, .empty_block, .block_single, => {},
1869 .@"if" => {
1870 const payload = node.castTag(.@"if").?.data;
1871 if (payload.@"else") |some|
1872 return addSemicolonIfNotBlock(c, some);
1873 return addSemicolonIfNotBlock(c, payload.then);
1874 },
1869 else => _ = try c.addToken(.semicolon, ";"),1875 else => _ = try c.addToken(.semicolon, ";"),
1870 }1876 }
1871}1877}
test/translate_c.zig+2-2
...@@ -11,12 +11,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -11,12 +11,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
11 \\}11 \\}
12 });12 });
1313
14 cases.add("variadic function demoted to prototype",14 cases.add("variadic function demoted to extern",
15 \\int foo(int bar, ...) {15 \\int foo(int bar, ...) {
16 \\ return 1;16 \\ return 1;
17 \\}17 \\}
18 , &[_][]const u8{18 , &[_][]const u8{
19 \\warning: TODO unable to translate variadic function, demoted to declaration19 \\warning: TODO unable to translate variadic function, demoted to extern
20 \\pub extern fn foo(bar: c_int, ...) c_int;20 \\pub extern fn foo(bar: c_int, ...) c_int;
21 });21 });
2222