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

Reply via email to