| author | |
| committer | |
| log | baaef7ed977a8c3d5df2aef673185101abc381d4 |
| tree | aa80b2e23a588684b4b1b0e2a18557882f5f569b |
| parent | bf678a12dfbdf0b3bb50804aa6b7ee081013049a |
| parent | eca294cd23b3b1cdb4a94fb37dfe52eeb0a7c51d |
| signature | Signed by PGP key 4AEE18F83AFDEB23 |
Better _Bool translation6 files changed, 65 insertions(+), 4 deletions(-)
src-self-hosted/clang.zig+1| ... | ... | @@ -805,6 +805,7 @@ pub extern fn ZigClangType_getPointeeType(self: ?*const struct_ZigClangType) str |
| 805 | 805 | pub extern fn ZigClangType_isVoidType(self: ?*const struct_ZigClangType) bool; |
| 806 | 806 | pub extern fn ZigClangType_isRecordType(self: ?*const struct_ZigClangType) bool; |
| 807 | 807 | pub extern fn ZigClangType_isArrayType(self: ?*const struct_ZigClangType) bool; |
| 808 | pub extern fn ZigClangType_isBooleanType(self: ?*const struct_ZigClangType) bool; | |
| 808 | 809 | pub extern fn ZigClangType_getTypeClassName(self: *const struct_ZigClangType) [*:0]const u8; |
| 809 | 810 | pub extern fn ZigClangType_getAsArrayTypeUnsafe(self: *const ZigClangType) *const ZigClangArrayType; |
| 810 | 811 | pub extern fn ZigClangType_getAsRecordType(self: *const ZigClangType) ?*const ZigClangRecordType; |
src-self-hosted/translate_c.zig+24-4| ... | ... | @@ -1285,7 +1285,7 @@ fn transDeclStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangDeclStmt) |
| 1285 | 1285 | try transExprCoercing(rp, scope, expr, .used, .r_value) |
| 1286 | 1286 | else |
| 1287 | 1287 | try transCreateNodeUndefinedLiteral(c); |
| 1288 | if (isBoolRes(init_node)) { | |
| 1288 | if (!qualTypeIsBoolean(qual_type) and isBoolRes(init_node)) { | |
| 1289 | 1289 | const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "@boolToInt"); |
| 1290 | 1290 | try builtin_node.params.push(init_node); |
| 1291 | 1291 | builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| ... | ... | @@ -1351,9 +1351,13 @@ fn transImplicitCastExpr( |
| 1351 | 1351 | return transCreateNodeInfixOp(rp, scope, &ptr_to_int.base, .BangEqual, op_token, rhs_node, result_used, false); |
| 1352 | 1352 | }, |
| 1353 | 1353 | .IntegralToBoolean => { |
| 1354 | // val != 0 | |
| 1355 | 1354 | const node = try transExpr(rp, scope, sub_expr, .used, .r_value); |
| 1356 | 1355 | |
| 1356 | // The expression is already a boolean one, return it as-is | |
| 1357 | if (isBoolRes(node)) | |
| 1358 | return node; | |
| 1359 | ||
| 1360 | // val != 0 | |
| 1357 | 1361 | const op_token = try appendToken(rp.c, .BangEqual, "!="); |
| 1358 | 1362 | const rhs_node = try transCreateNodeInt(rp.c, 0); |
| 1359 | 1363 | return transCreateNodeInfixOp(rp, scope, node, .BangEqual, op_token, rhs_node, result_used, false); |
| ... | ... | @@ -1409,6 +1413,10 @@ fn transBoolExpr( |
| 1409 | 1413 | } |
| 1410 | 1414 | } |
| 1411 | 1415 | |
| 1416 | fn exprIsBooleanType(expr: *const ZigClangExpr) bool { | |
| 1417 | return qualTypeIsBoolean(ZigClangExpr_getType(expr)); | |
| 1418 | } | |
| 1419 | ||
| 1412 | 1420 | fn isBoolRes(res: *ast.Node) bool { |
| 1413 | 1421 | switch (res.id) { |
| 1414 | 1422 | .InfixOp => switch (@fieldParentPtr(ast.Node.InfixOp, "base", res).op) { |
| ... | ... | @@ -1738,6 +1746,14 @@ fn transCCast( |
| 1738 | 1746 | builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| 1739 | 1747 | return &builtin_node.base; |
| 1740 | 1748 | } |
| 1749 | if (ZigClangType_isBooleanType(qualTypeCanon(src_type)) and | |
| 1750 | !ZigClangType_isBooleanType(qualTypeCanon(dst_type))) | |
| 1751 | { | |
| 1752 | const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "@boolToInt"); | |
| 1753 | try builtin_node.params.push(expr); | |
| 1754 | builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | |
| 1755 | return &builtin_node.base; | |
| 1756 | } | |
| 1741 | 1757 | if (ZigClangQualType_getTypeClass(ZigClangQualType_getCanonicalType(dst_type)) == .Enum) { |
| 1742 | 1758 | const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "@intToEnum"); |
| 1743 | 1759 | try builtin_node.params.push(try transQualType(rp, dst_type, loc)); |
| ... | ... | @@ -3089,6 +3105,10 @@ fn qualTypeIsPtr(qt: ZigClangQualType) bool { |
| 3089 | 3105 | return ZigClangType_getTypeClass(qualTypeCanon(qt)) == .Pointer; |
| 3090 | 3106 | } |
| 3091 | 3107 | |
| 3108 | fn qualTypeIsBoolean(qt: ZigClangQualType) bool { | |
| 3109 | return ZigClangType_isBooleanType(qualTypeCanon(qt)); | |
| 3110 | } | |
| 3111 | ||
| 3092 | 3112 | fn qualTypeIntBitWidth(rp: RestorePoint, qt: ZigClangQualType, source_loc: ZigClangSourceLocation) !u32 { |
| 3093 | 3113 | const ty = ZigClangQualType_getTypePtr(qt); |
| 3094 | 3114 | |
| ... | ... | @@ -3365,7 +3385,7 @@ fn transCreateNodeAssign( |
| 3365 | 3385 | const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value); |
| 3366 | 3386 | const eq_token = try appendToken(rp.c, .Equal, "="); |
| 3367 | 3387 | var rhs_node = try transExprCoercing(rp, scope, rhs, .used, .r_value); |
| 3368 | if (isBoolRes(rhs_node)) { | |
| 3388 | if (!exprIsBooleanType(lhs) and isBoolRes(rhs_node)) { | |
| 3369 | 3389 | const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "@boolToInt"); |
| 3370 | 3390 | try builtin_node.params.push(rhs_node); |
| 3371 | 3391 | builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| ... | ... | @@ -3390,7 +3410,7 @@ fn transCreateNodeAssign( |
| 3390 | 3410 | const node = try transCreateNodeVarDecl(rp.c, false, true, tmp); |
| 3391 | 3411 | node.eq_token = try appendToken(rp.c, .Equal, "="); |
| 3392 | 3412 | var rhs_node = try transExpr(rp, &block_scope.base, rhs, .used, .r_value); |
| 3393 | if (isBoolRes(rhs_node)) { | |
| 3413 | if (!exprIsBooleanType(lhs) and isBoolRes(rhs_node)) { | |
| 3394 | 3414 | const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "@boolToInt"); |
| 3395 | 3415 | try builtin_node.params.push(rhs_node); |
| 3396 | 3416 | builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); |
src/zig_clang.cpp+5| ... | ... | @@ -1814,6 +1814,11 @@ ZigClangQualType ZigClangType_getPointeeType(const ZigClangType *self) { |
| 1814 | 1814 | return bitcast(casted->getPointeeType()); |
| 1815 | 1815 | } |
| 1816 | 1816 | |
| 1817 | bool ZigClangType_isBooleanType(const ZigClangType *self) { | |
| 1818 | auto casted = reinterpret_cast<const clang::Type *>(self); | |
| 1819 | return casted->isBooleanType(); | |
| 1820 | } | |
| 1821 | ||
| 1817 | 1822 | bool ZigClangType_isVoidType(const ZigClangType *self) { |
| 1818 | 1823 | auto casted = reinterpret_cast<const clang::Type *>(self); |
| 1819 | 1824 | return casted->isVoidType(); |
src/zig_clang.h+1| ... | ... | @@ -932,6 +932,7 @@ ZIG_EXTERN_C bool ZigClangQualType_isRestrictQualified(struct ZigClangQualType); |
| 932 | 932 | |
| 933 | 933 | ZIG_EXTERN_C enum ZigClangTypeClass ZigClangType_getTypeClass(const struct ZigClangType *self); |
| 934 | 934 | ZIG_EXTERN_C struct ZigClangQualType ZigClangType_getPointeeType(const struct ZigClangType *self); |
| 935 | ZIG_EXTERN_C bool ZigClangType_isBooleanType(const struct ZigClangType *self); | |
| 935 | 936 | ZIG_EXTERN_C bool ZigClangType_isVoidType(const struct ZigClangType *self); |
| 936 | 937 | ZIG_EXTERN_C bool ZigClangType_isArrayType(const struct ZigClangType *self); |
| 937 | 938 | ZIG_EXTERN_C bool ZigClangType_isRecordType(const struct ZigClangType *self); |
test/run_translated_c.zig+17| ... | ... | @@ -3,6 +3,23 @@ const tests = @import("tests.zig"); |
| 3 | 3 | const nl = std.cstr.line_sep; |
| 4 | 4 | |
| 5 | 5 | pub fn addCases(cases: *tests.RunTranslatedCContext) void { |
| 6 | cases.add("boolean values and expressions", | |
| 7 | \\#include <stdlib.h> | |
| 8 | \\static const _Bool false_val = 0; | |
| 9 | \\static const _Bool true_val = 1; | |
| 10 | \\void foo(int x, int y) { | |
| 11 | \\ _Bool r = x < y; | |
| 12 | \\ if (!r) abort(); | |
| 13 | \\ _Bool self = foo; | |
| 14 | \\ if (self == false_val) abort(); | |
| 15 | \\} | |
| 16 | \\int main(int argc, char **argv) { | |
| 17 | \\ foo(2, 5); | |
| 18 | \\ if (false_val == true_val) abort(); | |
| 19 | \\ return 0; | |
| 20 | \\} | |
| 21 | , ""); | |
| 22 | ||
| 6 | 23 | cases.add("hello world", |
| 7 | 24 | \\#define _NO_CRT_STDIO_INLINE 1 |
| 8 | 25 | \\#include <stdio.h> |
test/translate_c.zig+17| ... | ... | @@ -2504,4 +2504,21 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 2504 | 2504 | \\ foo(@intToPtr([*c]c_int, @ptrToInt(a))); |
| 2505 | 2505 | \\} |
| 2506 | 2506 | }); |
| 2507 | ||
| 2508 | cases.add("handling of _Bool type", | |
| 2509 | \\_Bool foo(_Bool x) { | |
| 2510 | \\ _Bool a = x != 1; | |
| 2511 | \\ _Bool b = a != 0; | |
| 2512 | \\ _Bool c = foo; | |
| 2513 | \\ return foo(c != b); | |
| 2514 | \\} | |
| 2515 | , &[_][]const u8{ | |
| 2516 | \\pub export fn foo(arg_x: bool) bool { | |
| 2517 | \\ var x = arg_x; | |
| 2518 | \\ var a: bool = (@boolToInt(x) != @as(c_int, 1)); | |
| 2519 | \\ var b: bool = (@boolToInt(a) != @as(c_int, 0)); | |
| 2520 | \\ var c: bool = @ptrToInt(foo) != 0; | |
| 2521 | \\ return foo((@boolToInt(c) != @boolToInt(b))); | |
| 2522 | \\} | |
| 2523 | }); | |
| 2507 | 2524 | } |