Jump to page: 1 2
Thread overview
Spec on casting to integer with smaller range than value
Mar 28, 2020
Johan
Mar 28, 2020
Stefan Koch
Mar 28, 2020
Johan
Mar 29, 2020
user1234
Mar 29, 2020
Patrick Schluter
Mar 28, 2020
kinke
Mar 28, 2020
Dennis
Mar 28, 2020
kinke
Mar 28, 2020
Dennis
Mar 28, 2020
Dennis
Mar 28, 2020
kinke
Mar 29, 2020
Timon Gehr
March 28, 2020
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

March 28, 2020
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)
March 28, 2020
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.
March 28, 2020
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?
March 28, 2020
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.

March 28, 2020
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.

March 28, 2020
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
March 28, 2020
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).
March 28, 2020
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

March 29, 2020
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.
« First   ‹ Prev
1 2