www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Spec on casting to integer with smaller range than value

reply Johan <j j.nl> writes:
Hi all,
   Where can I read in the spec what the outcomes of the following 
are?

```
uint a = 260;
auto b = cast(ubyte) a;

float f = 1.203125f  * 255.0f;
auto zz =  cast(ubyte) f;
// https://github.com/ldc-developers/ldc/issues/3237
```

Thanks,
   Johan
Mar 28
next sibling parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Saturday, 28 March 2020 at 12:09:49 UTC, Johan wrote:
 Hi all,
   Where can I read in the spec what the outcomes of the 
 following are?

 ```
 uint a = 260;
 auto b = cast(ubyte) a;

 float f = 1.203125f  * 255.0f;
 auto zz =  cast(ubyte) f;
 // https://github.com/ldc-developers/ldc/issues/3237
 ```

 Thanks,
   Johan
cast (ubyte)x is the same as = ((cast(uint)x) & 0xff)
Mar 28
parent reply Johan <j j.nl> writes:
On Saturday, 28 March 2020 at 15:23:19 UTC, Stefan Koch wrote:
 cast (ubyte)x is the same as = ((cast(uint)x) & 0xff)
Where does the spec say that? -Johan
Mar 28
next sibling parent user1234 <user1234 12.de> writes:
On Saturday, 28 March 2020 at 19:11:04 UTC, Johan wrote:
 On Saturday, 28 March 2020 at 15:23:19 UTC, Stefan Koch wrote:
 cast (ubyte)x is the same as = ((cast(uint)x) & 0xff)
Where does the spec say that? -Johan
 cast(uint)x
is the trunc() that happens when casting a FP to integral type. https://dlang.org/spec/expression.html#cast_expressions §7.
 & 0xFF
is not specified but is the normal part of the cast uint -> ubyte.
Mar 28
prev sibling parent Patrick Schluter <Patrick.Schluter bbox.fr> writes:
On Saturday, 28 March 2020 at 19:11:04 UTC, Johan wrote:
 On Saturday, 28 March 2020 at 15:23:19 UTC, Stefan Koch wrote:
 cast (ubyte)x is the same as = ((cast(uint)x) & 0xff)
Where does the spec say that?
It's a consequence of the int promotion rule D adheres to.
Mar 29
prev sibling parent reply kinke <noone nowhere.com> writes:
On Saturday, 28 March 2020 at 12:09:49 UTC, Johan wrote:
 float f = 1.203125f  * 255.0f;
 auto zz =  cast(ubyte) f;
 // https://github.com/ldc-developers/ldc/issues/3237
The 2nd cast, float to int, should be https://dlang.org/spec/expression.html#cast_expressions, §7: 'Casting a floating point value to an integral type is the equivalent of converting to an integer using truncation.' It doesn't specify the behavior if that integer doesn't fit; that should probably be explicitly mentioned as undefined behavior, to account for the observed LLVM/gcc behavior.
Mar 28
next sibling parent reply Dennis <dkorpel gmail.com> writes:
On Saturday, 28 March 2020 at 15:33:35 UTC, kinke wrote:
 that should probably be explicitly mentioned as undefined 
 behavior, to account for the observed LLVM/gcc behavior.
Which would make `cast(int) someFloat` not allowed in safe code. Is there any chance LLVM could be instructed to treat it as implementation-defined behavior?
Mar 28
next sibling parent reply kinke <noone nowhere.com> writes:
On Saturday, 28 March 2020 at 15:47:04 UTC, Dennis wrote:
 On Saturday, 28 March 2020 at 15:33:35 UTC, kinke wrote:
 that should probably be explicitly mentioned as undefined 
 behavior, to account for the observed LLVM/gcc behavior.
Which would make `cast(int) someFloat` not allowed in safe code.
safe is about memory corruption, not about disallowing any undefined behavior.
Mar 28
parent reply Dennis <dkorpel gmail.com> writes:
On Saturday, 28 March 2020 at 16:06:39 UTC, kinke wrote:
  safe is about memory corruption, not about disallowing any 
 undefined behavior.
The spec provides two definitions:
 Safe functions are functions that are statically checked to 
 exhibit no possibility of undefined behavior. Undefined 
 behavior is often used as a vector for malicious attacks.
https://dlang.org/spec/function.html#function-safety
 Memory Safety for a program is defined as it being impossible 
 for the program to corrupt memory. Therefore, the safe subset 
 of D consists only of programming language features that are 
 guaranteed to never result in memory corruption.
https://dlang.org/spec/memory-safe-d.html Presence of undefined behavior is sufficient to cause memory corruption, and memory corruption itself is undefined behavior, so the definitions are equivalent and both describe the same thing.
Mar 28
parent Dennis <dkorpel gmail.com> writes:
On Saturday, 28 March 2020 at 16:15:08 UTC, Dennis wrote:
 Presence of undefined behavior is sufficient to cause memory 
 corruption, and memory corruption itself is undefined behavior, 
 so the definitions are equivalent and both describe the same 
 thing.
This came up before in different discussions: https://github.com/dlang/dlang.org/pull/2578#discussion_r257200332 https://forum.dlang.org/post/qu53go$r6v$1 digitalmars.com
Mar 28
prev sibling parent kinke <noone nowhere.com> writes:
On Saturday, 28 March 2020 at 15:47:04 UTC, Dennis wrote:
 Which would make `cast(int) someFloat` not allowed in  safe 
 code.
In LLVM lingo, the out-of-bounds cast wouldn't be undefined behavior per se, but yield a 'poison' value, whose later usage might eventually trigger undefined behavior, depending on what exactly you're doing with it.
 Safe functions are functions that are statically checked to 
 exhibit no possibility of undefined behavior.
If that's really the ultimate goal, then these casts would probably need a prefixed bounds check in safe code, just like an array bounds check (incl. omitting it if it can be statically determined to fit).
Mar 28
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 28.03.20 16:33, kinke wrote:
 that should probably be explicitly mentioned as undefined behavior, to 
 account for the observed LLVM/gcc behavior.
It can't be full-blown UB as such a cast works in safe code.
Mar 29