Normalize behavior of cast to Boolean types
Before this patch, casting int/uint to a Boolean type would sometimes give a
true value if the int/uint was nonzero, but sometimes truncate the int/uint
to the size of the Boolean.
The included test case demonstrates this problem (and should always print out
'true'). Code using default-width Bools worked OK because of the C99 _Bool
rules, but any cast to non-default width Boolean type or any cast to a Boolean
type with the LLVM backend did not work properly.
The simple fix in expr.cpp was to:
1) modify a call to codegenCast to pass the Chapel type instead of
type->symbol->cname, so that we can call is_bool_type on it.
2) modify the codegenCast that takes in a Chapel type to handle Boolean
types specially.
Verified with CHPL_LLVM=none make check and checked that the new test works
with and without --llvm. (and started a full local/C test-suite run; so
far so good).
Future Work: update the spec to describe the behavior of casts to Bool.
Index: compiler/AST/expr.cpp
===================================================================
--- compiler/AST/expr.cpp (revision 22995)
+++ compiler/AST/expr.cpp (working copy)
@@ -2827,7 +2827,10 @@
GenRet ret;
ret.chplType = t;
ret.isLVPtr = value.isLVPtr;
-
+
+ // If we are casting to bool, set it to != 0.
+ if( is_bool_type(t) ) return codegenNotEquals(value, codegenZero());
+
// if we are casting a C99 wide pointer, parens around the value
// will result in an error, hence the Cparens parameter
// e.g. ((chpl____wide_DefaultRectangularArr_locale_1_int64_t_F)(
@@ -4857,7 +4860,7 @@
fprintf(outfile, "))))");*/
} else {
GenRet v = codegenValue(get(2));
- ret = codegenCast(typeInfo()->symbol->cname, v);
+ ret = codegenCast(typeInfo(), v);
}
}
break;
Index: test/users/ferguson/cast_to_bool.chpl
===================================================================
--- test/users/ferguson/cast_to_bool.chpl (revision 0)
+++ test/users/ferguson/cast_to_bool.chpl (revision 0)
@@ -0,0 +1,106 @@
+proc foo(x:uint, y:uint)
+{
+ writeln((x & y):bool);
+}
+
+writeln((0x3 & 0x1):bool);
+foo(0x3, 0x1);
+writeln((0x300 & 0x100):bool);
+foo(0x300, 0x100);
+writeln((0x30000 & 0x10000):bool);
+foo(0x30000, 0x10000);
+writeln((0x3000000 & 0x1000000):bool);
+foo(0x3000000, 0x1000000);
+writeln((0x300000000 & 0x100000000):bool);
+foo(0x300000000, 0x100000000);
+writeln((0x30000000000 & 0x10000000000):bool);
+foo(0x30000000000, 0x10000000000);
+writeln((0x3000000000000 & 0x1000000000000):bool);
+foo(0x3000000000000, 0x1000000000000);
+
+proc foo8(x:uint, y:uint)
+{
+ writeln((x & y):bool(8));
+}
+
+
+writeln((0x3 & 0x1):bool(8));
+foo8(0x3, 0x1);
+writeln((0x300 & 0x100):bool(8));
+foo8(0x300, 0x100);
+writeln((0x30000 & 0x10000):bool(8));
+foo8(0x30000, 0x10000);
+writeln((0x3000000 & 0x1000000):bool(8));
+foo8(0x3000000, 0x1000000);
+writeln((0x300000000 & 0x100000000):bool(8));
+foo8(0x300000000, 0x100000000);
+writeln((0x30000000000 & 0x10000000000):bool(8));
+foo8(0x30000000000, 0x10000000000);
+writeln((0x3000000000000 & 0x1000000000000):bool(8));
+foo8(0x3000000000000, 0x1000000000000);
+
+proc foo16(x:uint, y:uint)
+{
+ writeln((x & y):bool(16));
+}
+
+
+writeln((0x3 & 0x1):bool(16));
+foo16(0x3, 0x1);
+writeln((0x300 & 0x100):bool(16));
+foo16(0x300, 0x100);
+writeln((0x30000 & 0x10000):bool(16));
+foo16(0x30000, 0x10000);
+writeln((0x3000000 & 0x1000000):bool(16));
+foo16(0x3000000, 0x1000000);
+writeln((0x300000000 & 0x100000000):bool(16));
+foo16(0x300000000, 0x100000000);
+writeln((0x30000000000 & 0x10000000000):bool(16));
+foo16(0x30000000000, 0x10000000000);
+writeln((0x3000000000000 & 0x1000000000000):bool(16));
+foo16(0x3000000000000, 0x1000000000000);
+
+
+proc foo32(x:uint, y:uint)
+{
+ writeln((x & y):bool(32));
+}
+
+
+writeln((0x3 & 0x1):bool(32));
+foo32(0x3, 0x1);
+writeln((0x300 & 0x100):bool(32));
+foo32(0x300, 0x100);
+writeln((0x30000 & 0x10000):bool(32));
+foo32(0x30000, 0x10000);
+writeln((0x3000000 & 0x1000000):bool(32));
+foo32(0x3000000, 0x1000000);
+writeln((0x300000000 & 0x100000000):bool(32));
+foo32(0x300000000, 0x100000000);
+writeln((0x30000000000 & 0x10000000000):bool(32));
+foo32(0x30000000000, 0x10000000000);
+writeln((0x3000000000000 & 0x1000000000000):bool(32));
+foo32(0x3000000000000, 0x1000000000000);
+
+proc foo64(x:uint, y:uint)
+{
+ writeln((x & y):bool(64));
+}
+
+
+writeln((0x3 & 0x1):bool(64));
+foo64(0x3, 0x1);
+writeln((0x300 & 0x100):bool(64));
+foo64(0x300, 0x100);
+writeln((0x30000 & 0x10000):bool(64));
+foo64(0x30000, 0x10000);
+writeln((0x3000000 & 0x1000000):bool(64));
+foo64(0x3000000, 0x1000000);
+writeln((0x300000000 & 0x100000000):bool(64));
+foo64(0x300000000, 0x100000000);
+writeln((0x30000000000 & 0x10000000000):bool(64));
+foo64(0x30000000000, 0x10000000000);
+writeln((0x3000000000000 & 0x1000000000000):bool(64));
+foo64(0x3000000000000, 0x1000000000000);
+
+
Index: test/users/ferguson/cast_to_bool.good
===================================================================
--- test/users/ferguson/cast_to_bool.good (revision 0)
+++ test/users/ferguson/cast_to_bool.good (revision 0)
@@ -0,0 +1,70 @@
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
------------------------------------------------------------------------------
_______________________________________________
Chapel-developers mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/chapel-developers