authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-01-06 19:21:55-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-01-06 19:21:55-05:00
logbaaef7ed977a8c3d5df2aef673185101abc381d4
treeaa80b2e23a588684b4b1b0e2a18557882f5f569b
parentbf678a12dfbdf0b3bb50804aa6b7ee081013049a
parenteca294cd23b3b1cdb4a94fb37dfe52eeb0a7c51d
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #4083 from LemonBoy/better-stdbool

Better _Bool translation

6 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,6 +805,7 @@ pub extern fn ZigClangType_getPointeeType(self: ?*const struct_ZigClangType) str
805pub extern fn ZigClangType_isVoidType(self: ?*const struct_ZigClangType) bool;805pub extern fn ZigClangType_isVoidType(self: ?*const struct_ZigClangType) bool;
806pub extern fn ZigClangType_isRecordType(self: ?*const struct_ZigClangType) bool;806pub extern fn ZigClangType_isRecordType(self: ?*const struct_ZigClangType) bool;
807pub extern fn ZigClangType_isArrayType(self: ?*const struct_ZigClangType) bool;807pub extern fn ZigClangType_isArrayType(self: ?*const struct_ZigClangType) bool;
808pub extern fn ZigClangType_isBooleanType(self: ?*const struct_ZigClangType) bool;
808pub extern fn ZigClangType_getTypeClassName(self: *const struct_ZigClangType) [*:0]const u8;809pub extern fn ZigClangType_getTypeClassName(self: *const struct_ZigClangType) [*:0]const u8;
809pub extern fn ZigClangType_getAsArrayTypeUnsafe(self: *const ZigClangType) *const ZigClangArrayType;810pub extern fn ZigClangType_getAsArrayTypeUnsafe(self: *const ZigClangType) *const ZigClangArrayType;
810pub extern fn ZigClangType_getAsRecordType(self: *const ZigClangType) ?*const ZigClangRecordType;811pub 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,7 +1285,7 @@ fn transDeclStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangDeclStmt)
1285 try transExprCoercing(rp, scope, expr, .used, .r_value)1285 try transExprCoercing(rp, scope, expr, .used, .r_value)
1286 else1286 else
1287 try transCreateNodeUndefinedLiteral(c);1287 try transCreateNodeUndefinedLiteral(c);
1288 if (isBoolRes(init_node)) {1288 if (!qualTypeIsBoolean(qual_type) and isBoolRes(init_node)) {
1289 const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "@boolToInt");1289 const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "@boolToInt");
1290 try builtin_node.params.push(init_node);1290 try builtin_node.params.push(init_node);
1291 builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");1291 builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
...@@ -1351,9 +1351,13 @@ fn transImplicitCastExpr(...@@ -1351,9 +1351,13 @@ fn transImplicitCastExpr(
1351 return transCreateNodeInfixOp(rp, scope, &ptr_to_int.base, .BangEqual, op_token, rhs_node, result_used, false);1351 return transCreateNodeInfixOp(rp, scope, &ptr_to_int.base, .BangEqual, op_token, rhs_node, result_used, false);
1352 },1352 },
1353 .IntegralToBoolean => {1353 .IntegralToBoolean => {
1354 // val != 0
1355 const node = try transExpr(rp, scope, sub_expr, .used, .r_value);1354 const node = try transExpr(rp, scope, sub_expr, .used, .r_value);
13561355
1356 // The expression is already a boolean one, return it as-is
1357 if (isBoolRes(node))
1358 return node;
1359
1360 // val != 0
1357 const op_token = try appendToken(rp.c, .BangEqual, "!=");1361 const op_token = try appendToken(rp.c, .BangEqual, "!=");
1358 const rhs_node = try transCreateNodeInt(rp.c, 0);1362 const rhs_node = try transCreateNodeInt(rp.c, 0);
1359 return transCreateNodeInfixOp(rp, scope, node, .BangEqual, op_token, rhs_node, result_used, false);1363 return transCreateNodeInfixOp(rp, scope, node, .BangEqual, op_token, rhs_node, result_used, false);
...@@ -1409,6 +1413,10 @@ fn transBoolExpr(...@@ -1409,6 +1413,10 @@ fn transBoolExpr(
1409 }1413 }
1410}1414}
14111415
1416fn exprIsBooleanType(expr: *const ZigClangExpr) bool {
1417 return qualTypeIsBoolean(ZigClangExpr_getType(expr));
1418}
1419
1412fn isBoolRes(res: *ast.Node) bool {1420fn isBoolRes(res: *ast.Node) bool {
1413 switch (res.id) {1421 switch (res.id) {
1414 .InfixOp => switch (@fieldParentPtr(ast.Node.InfixOp, "base", res).op) {1422 .InfixOp => switch (@fieldParentPtr(ast.Node.InfixOp, "base", res).op) {
...@@ -1738,6 +1746,14 @@ fn transCCast(...@@ -1738,6 +1746,14 @@ fn transCCast(
1738 builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");1746 builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
1739 return &builtin_node.base;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 if (ZigClangQualType_getTypeClass(ZigClangQualType_getCanonicalType(dst_type)) == .Enum) {1757 if (ZigClangQualType_getTypeClass(ZigClangQualType_getCanonicalType(dst_type)) == .Enum) {
1742 const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "@intToEnum");1758 const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "@intToEnum");
1743 try builtin_node.params.push(try transQualType(rp, dst_type, loc));1759 try builtin_node.params.push(try transQualType(rp, dst_type, loc));
...@@ -3089,6 +3105,10 @@ fn qualTypeIsPtr(qt: ZigClangQualType) bool {...@@ -3089,6 +3105,10 @@ fn qualTypeIsPtr(qt: ZigClangQualType) bool {
3089 return ZigClangType_getTypeClass(qualTypeCanon(qt)) == .Pointer;3105 return ZigClangType_getTypeClass(qualTypeCanon(qt)) == .Pointer;
3090}3106}
30913107
3108fn qualTypeIsBoolean(qt: ZigClangQualType) bool {
3109 return ZigClangType_isBooleanType(qualTypeCanon(qt));
3110}
3111
3092fn qualTypeIntBitWidth(rp: RestorePoint, qt: ZigClangQualType, source_loc: ZigClangSourceLocation) !u32 {3112fn qualTypeIntBitWidth(rp: RestorePoint, qt: ZigClangQualType, source_loc: ZigClangSourceLocation) !u32 {
3093 const ty = ZigClangQualType_getTypePtr(qt);3113 const ty = ZigClangQualType_getTypePtr(qt);
30943114
...@@ -3365,7 +3385,7 @@ fn transCreateNodeAssign(...@@ -3365,7 +3385,7 @@ fn transCreateNodeAssign(
3365 const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value);3385 const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value);
3366 const eq_token = try appendToken(rp.c, .Equal, "=");3386 const eq_token = try appendToken(rp.c, .Equal, "=");
3367 var rhs_node = try transExprCoercing(rp, scope, rhs, .used, .r_value);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 const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "@boolToInt");3389 const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "@boolToInt");
3370 try builtin_node.params.push(rhs_node);3390 try builtin_node.params.push(rhs_node);
3371 builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");3391 builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
...@@ -3390,7 +3410,7 @@ fn transCreateNodeAssign(...@@ -3390,7 +3410,7 @@ fn transCreateNodeAssign(
3390 const node = try transCreateNodeVarDecl(rp.c, false, true, tmp);3410 const node = try transCreateNodeVarDecl(rp.c, false, true, tmp);
3391 node.eq_token = try appendToken(rp.c, .Equal, "=");3411 node.eq_token = try appendToken(rp.c, .Equal, "=");
3392 var rhs_node = try transExpr(rp, &block_scope.base, rhs, .used, .r_value);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 const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "@boolToInt");3414 const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "@boolToInt");
3395 try builtin_node.params.push(rhs_node);3415 try builtin_node.params.push(rhs_node);
3396 builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");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,6 +1814,11 @@ ZigClangQualType ZigClangType_getPointeeType(const ZigClangType *self) {
1814 return bitcast(casted->getPointeeType());1814 return bitcast(casted->getPointeeType());
1815}1815}
18161816
1817bool ZigClangType_isBooleanType(const ZigClangType *self) {
1818 auto casted = reinterpret_cast<const clang::Type *>(self);
1819 return casted->isBooleanType();
1820}
1821
1817bool ZigClangType_isVoidType(const ZigClangType *self) {1822bool ZigClangType_isVoidType(const ZigClangType *self) {
1818 auto casted = reinterpret_cast<const clang::Type *>(self);1823 auto casted = reinterpret_cast<const clang::Type *>(self);
1819 return casted->isVoidType();1824 return casted->isVoidType();
src/zig_clang.h+1
...@@ -932,6 +932,7 @@ ZIG_EXTERN_C bool ZigClangQualType_isRestrictQualified(struct ZigClangQualType);...@@ -932,6 +932,7 @@ ZIG_EXTERN_C bool ZigClangQualType_isRestrictQualified(struct ZigClangQualType);
932932
933ZIG_EXTERN_C enum ZigClangTypeClass ZigClangType_getTypeClass(const struct ZigClangType *self);933ZIG_EXTERN_C enum ZigClangTypeClass ZigClangType_getTypeClass(const struct ZigClangType *self);
934ZIG_EXTERN_C struct ZigClangQualType ZigClangType_getPointeeType(const struct ZigClangType *self);934ZIG_EXTERN_C struct ZigClangQualType ZigClangType_getPointeeType(const struct ZigClangType *self);
935ZIG_EXTERN_C bool ZigClangType_isBooleanType(const struct ZigClangType *self);
935ZIG_EXTERN_C bool ZigClangType_isVoidType(const struct ZigClangType *self);936ZIG_EXTERN_C bool ZigClangType_isVoidType(const struct ZigClangType *self);
936ZIG_EXTERN_C bool ZigClangType_isArrayType(const struct ZigClangType *self);937ZIG_EXTERN_C bool ZigClangType_isArrayType(const struct ZigClangType *self);
937ZIG_EXTERN_C bool ZigClangType_isRecordType(const struct ZigClangType *self);938ZIG_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,6 +3,23 @@ const tests = @import("tests.zig");
3const nl = std.cstr.line_sep;3const nl = std.cstr.line_sep;
44
5pub fn addCases(cases: *tests.RunTranslatedCContext) void {5pub 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 cases.add("hello world",23 cases.add("hello world",
7 \\#define _NO_CRT_STDIO_INLINE 124 \\#define _NO_CRT_STDIO_INLINE 1
8 \\#include <stdio.h>25 \\#include <stdio.h>
test/translate_c.zig+17
...@@ -2504,4 +2504,21 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -2504,4 +2504,21 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
2504 \\ foo(@intToPtr([*c]c_int, @ptrToInt(a)));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}