Compiler bug ? -preview=intpromote and Integral promotion rules not being followed for unary + - ~ operators

wjoe invalid at example.com
Thu May 14 17:44:46 UTC 2020


I have a container which provides access to data via a handle. 
For book keeping I calculate some bitmasks.
Previously, when the handle type as well as the constants were 
uint, everything compiled fine.
Today I added a template parameter to be able to specify the 
handle type and I ran into this problem.

I've read the following information on the matter:

https://forum.dlang.org/thread/yqfhytyhivltamujdhgb@forum.dlang.org
https://issues.dlang.org/show_bug.cgi?id=18380
https://dlang.org/changelog/2.078.0.html#fix16997

However I still don't see the problem with regards to unsigned 
types.
Why is it necessary to promote a ushort or ubyte to int for the 
purpose of shifting or the one's complement ?
At least the code at the bottom of the post seems to produce 
correct results.

One problem I see with the bug fix is that, AFAIK, the int type 
in C is not a fixed bit type like it is in D where it is defined 
to be 32 bit and therefore casting to int in D can't really 
reproduce the C behavior. What  am I missing ?

Back to my container.
* Using a 32 bit type, i.e. uint, everything compiles fine.

* Using a 16 or 8 bit type, i.e. ushort and ubyte, the compiler 
complains with -preview=intpromote for the pragmas and errors out 
on assignments of the same types.
i.e. e.g.

alias handle_t = ushort;
enum handle_t MASK = 0x8000;
handle_t handle = ~MASK; // the error message is basically: 
[value is promoted to int and] 32769 can't be assigned to ushort

* Using a 64 bit type, i.e. ulong, the whole thing blows up 
because the compiler pro-, or rather, demotes the ulong to int 
and int << 40 is obviously violating a constraint of 0..31 for 
32bit types.

void main()
{
     import std.conv: to;
     import std.stdio;
     alias t = ushort;
     enum t m = 0x8000;
     pragma (msg, m.to!string(16));
     pragma (msg, (~m).to!string(16));
     pragma (msg, (cast(int)m).to!string(16));
     pragma (msg, (~cast(int)m).to!string(16));
}

2.063  : Success with output:
-----
8000
7FFF
8000
FFFFFFFFFFFF7FFF
-----

2.064   to 2.077.1: Success with output:
-----
8000
7FFF
8000
FFFF7FFF
-----

2.078.1 to 2.084.1: Success with output:
-----
8000
onlineapp.d(8): Deprecation: integral promotion not done for 
`~cast(ushort)32768u`, use '-transition=intpromote' switch or 
`~cast(int)(cast(ushort)32768u)`
7FFF
8000
FFFF7FFF
-----

Apart from the fact that I end up with an int, which causes all 
kinds of havoc and the annoyance that i need to cast a ushort to 
ushort to be able to assign it to a ushort, it appears to me that 
all the results are correct.


More information about the Digitalmars-d-learn mailing list