www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - phobos's circle CI runs a busted version of DMD

reply deadalnix <deadalnix gmail.com> writes:
Sample code:
```d
     ushort ee = 1028;
     ee <<= 5U;
     ee >>= 5U;
     writeln(ee);
```

Regular compiler: https://godbolt.org/z/TcbjP76fW (prints 1028)
Circle CI: 64516 .

Someone, the compiler manages to do a signed arithmetic shift on 
an unsigned.
Jan 10 2023
next sibling parent reply Max Haughton <maxhaton gmail.com> writes:
On Wednesday, 11 January 2023 at 01:03:33 UTC, deadalnix wrote:
 Sample code:
 ```d
     ushort ee = 1028;
     ee <<= 5U;
     ee >>= 5U;
     writeln(ee);
 ```

 Regular compiler: https://godbolt.org/z/TcbjP76fW (prints 1028)
 Circle CI: 64516 .

 Someone, the compiler manages to do a signed arithmetic shift 
 on an unsigned.
https://godbolt.org/z/M3fGE9bqY "All versions: Success with output: 64516" from run.dlang.io
Jan 10 2023
parent reply Dom DiSc <dominikus scherkl.de> writes:
On Wednesday, 11 January 2023 at 02:50:52 UTC, Max Haughton wrote:
 On Wednesday, 11 January 2023 at 01:03:33 UTC, deadalnix wrote:
 Regular compiler: https://godbolt.org/z/TcbjP76fW (prints 1028)
 Circle CI: 64516 .

 Someone, the compiler manages to do a signed arithmetic shift 
 on an unsigned.
https://godbolt.org/z/M3fGE9bqY "All versions: Success with output: 64516" from run.dlang.io
Ok, so Godbolt also runs a busted version of DMD? And why counts 64516 as a success here?!?!
Jan 11 2023
next sibling parent deadalnix <deadalnix gmail.com> writes:
On Wednesday, 11 January 2023 at 11:04:50 UTC, Dom DiSc wrote:
 https://godbolt.org/z/M3fGE9bqY

 "All versions: Success with output: 64516" from run.dlang.io
Ok, so Godbolt also runs a busted version of DMD? And why counts 64516 as a success here?!?!
Congratulation for understanding exactly backward. 64516 is not a success, it is a failure.
Jan 11 2023
prev sibling parent max haughton <maxhaton gmail.com> writes:
On Wednesday, 11 January 2023 at 11:04:50 UTC, Dom DiSc wrote:
 On Wednesday, 11 January 2023 at 02:50:52 UTC, Max Haughton 
 wrote:
 On Wednesday, 11 January 2023 at 01:03:33 UTC, deadalnix wrote:
 Regular compiler: https://godbolt.org/z/TcbjP76fW (prints 
 1028)
 Circle CI: 64516 .

 Someone, the compiler manages to do a signed arithmetic shift 
 on an unsigned.
https://godbolt.org/z/M3fGE9bqY "All versions: Success with output: 64516" from run.dlang.io
Ok, so Godbolt also runs a busted version of DMD? And why counts 64516 as a success here?!?!
Success here merely means that it compiled. The "run with all dmd versions" mode is aimed for finding regressions and so on.
Jan 11 2023
prev sibling next sibling parent reply Dukc <ajieskola gmail.com> writes:
On Wednesday, 11 January 2023 at 01:03:33 UTC, deadalnix wrote:
 Sample code:
 ```d
     ushort ee = 1028;
     ee <<= 5U;
     ee >>= 5U;
     writeln(ee);
 ```

 Regular compiler: https://godbolt.org/z/TcbjP76fW (prints 1028)
 Circle CI: 64516 .

 Someone, the compiler manages to do a signed arithmetic shift 
 on an unsigned.
[The spec says](https://dlang.org/spec/expression.html#shift_expressions) that `>>` means *signed* shift right. `>>>` is for unsigned shifts. So pedantically speaking, 64516 is the correct result. It's another issue whether that's good design though. For one, it breaks the rule "do what C does, or don't compile". It'd be more reasonable if `>>` was type-dependant shift right (as in C) IMO.
Jan 11 2023
next sibling parent reply jmh530 <john.michael.hall gmail.com> writes:
On Wednesday, 11 January 2023 at 13:26:57 UTC, Dukc wrote:
 On Wednesday, 11 January 2023 at 01:03:33 UTC, deadalnix wrote:
 Sample code:
 ```d
     ushort ee = 1028;
     ee <<= 5U;
     ee >>= 5U;
     writeln(ee);
 ```

 Regular compiler: https://godbolt.org/z/TcbjP76fW (prints 1028)
 Circle CI: 64516 .

 Someone, the compiler manages to do a signed arithmetic shift 
 on an unsigned.
[The spec says](https://dlang.org/spec/expression.html#shift_expressions) that `>>` means *signed* shift right. `>>>` is for unsigned shifts. So pedantically speaking, 64516 is the correct result. It's another issue whether that's good design though. For one, it breaks the rule "do what C does, or don't compile". It'd be more reasonable if `>>` was type-dependant shift right (as in C) IMO.
Not really. If you just do `>>` (i.e. not `>>=`), then you get 1028. ```d import core.stdc.stdio: printf; void main() { ushort ee = 32896; //starting from the second shift ushort ee_result = ee >> 5u; printf("the value of ee_result is %d\n", ee_result); //the value of ee_result is 1028 } ``` The problem is the combination with assignment, which is what makes it seem like a bug. According to [1], "the right operand is implicitly converted to the type of the left operand, and assigned to it." So what should happen is that `5U` is implicitly converted to `5` and a signed conversion should happen. The result should be 1028. 64516 seems like a weird result. [1] https://dlang.org/spec/expression.html#simple_assignment_expressions
Jan 11 2023
next sibling parent jmh530 <john.michael.hall gmail.com> writes:
On Wednesday, 11 January 2023 at 13:51:43 UTC, jmh530 wrote:
 On Wednesday, 11 January 2023 at 13:26:57 UTC, Dukc wrote:
 On Wednesday, 11 January 2023 at 01:03:33 UTC, deadalnix wrote:
 Sample code:
 ```d
     ushort ee = 1028;
     ee <<= 5U;
     ee >>= 5U;
     writeln(ee);
 ```

 Regular compiler: https://godbolt.org/z/TcbjP76fW (prints 
 1028)
 Circle CI: 64516 .

 Someone, the compiler manages to do a signed arithmetic shift 
 on an unsigned.
[The spec says](https://dlang.org/spec/expression.html#shift_expressions) that `>>` means *signed* shift right. `>>>` is for unsigned shifts. So pedantically speaking, 64516 is the correct result. It's another issue whether that's good design though. For one, it breaks the rule "do what C does, or don't compile". It'd be more reasonable if `>>` was type-dependant shift right (as in C) IMO.
Not really. If you just do `>>` (i.e. not `>>=`), then you get 1028. ```d import core.stdc.stdio: printf; void main() { ushort ee = 32896; //starting from the second shift ushort ee_result = ee >> 5u; printf("the value of ee_result is %d\n", ee_result); //the value of ee_result is 1028 } ``` The problem is the combination with assignment, which is what makes it seem like a bug. According to [1], "the right operand is implicitly converted to the type of the left operand, and assigned to it." So what should happen is that `5U` is implicitly converted to `5` and a signed conversion should happen. The result should be 1028. 64516 seems like a weird result. [1] https://dlang.org/spec/expression.html#simple_assignment_expressions
Upon further investigation, the problem goes away when you cast `5u` to ushort (since `5u` is a uint and not a ushort). ```d import core.stdc.stdio: printf; void main() { ushort ee = 32896; //starting from the second shift ee >>= (cast(ushort) 5u); printf("the value of ee is %d\n", ee); //the value of ee is 1028 } ``` Not quite sure why the problem is there for the uint and not the ushort, but it could be related to the sequence of integer promotion and the casting. What happens seems inconsistent with the spec. One weird thing is that if you change the cast from ushort to ulong, then we don't have the problem. It is only uint where we get the weird result.
Jan 11 2023
prev sibling parent reply Paul Backus <snarwin gmail.com> writes:
On Wednesday, 11 January 2023 at 13:51:43 UTC, jmh530 wrote:
 The problem is the combination with assignment, which is what 
 makes it seem like a bug. According to [1], "the right operand 
 is implicitly converted to the type of the left operand, and 
 assigned to it."

 [1] 
 https://dlang.org/spec/expression.html#simple_assignment_expressions
The relevant section of the spec here is the one about "Assignment Operator Expressions" [2], which states that
 For arguments of built-in types, assignment operator 
 expressions such as

     a op= b

 are semantically equivalent to:

     a = cast(typeof(a))(a op b)
If we rewrite deadalnix's example using this equivalence, we get the following code: ushort ee = 1028; ee = cast(ushort)(ee << 5U); ee = cast(ushort)(ee >> 5U); writeln(ee); ...which prints 1028. So the behavior of the original example is unambiguously a violation of the language spec. [2] https://dlang.org/spec/expression.html#assignment_operator_expressions
Jan 11 2023
next sibling parent reply jmh530 <john.michael.hall gmail.com> writes:
On Wednesday, 11 January 2023 at 20:55:33 UTC, Paul Backus wrote:
 [snip]
 ...which prints 1028. So the behavior of the original example 
 is unambiguously a violation of the language spec.

 [2] 
 https://dlang.org/spec/expression.html#assignment_operator_expressions
So someone file a bug report...
Jan 11 2023
parent reply max haughton <maxhaton gmail.com> writes:
On Wednesday, 11 January 2023 at 20:57:00 UTC, jmh530 wrote:
 On Wednesday, 11 January 2023 at 20:55:33 UTC, Paul Backus 
 wrote:
 [snip]
 ...which prints 1028. So the behavior of the original example 
 is unambiguously a violation of the language spec.

 [2] 
 https://dlang.org/spec/expression.html#assignment_operator_expressions
So someone file a bug report...
I filed one last night
Jan 11 2023
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/11/2023 2:31 PM, max haughton wrote:
 I filed one last night
Thank you. Link?
Jan 11 2023
parent reply max haughton <maxhaton gmail.com> writes:
On Wednesday, 11 January 2023 at 23:22:45 UTC, Walter Bright 
wrote:
 On 1/11/2023 2:31 PM, max haughton wrote:
 I filed one last night
Thank you. Link?
https://issues.dlang.org/show_bug.cgi?id=23618
Jan 11 2023
parent reply deadalnix <deadalnix gmail.com> writes:
On Thursday, 12 January 2023 at 02:05:14 UTC, max haughton wrote:
 On Wednesday, 11 January 2023 at 23:22:45 UTC, Walter Bright 
 wrote:
 On 1/11/2023 2:31 PM, max haughton wrote:
 I filed one last night
Thank you. Link?
https://issues.dlang.org/show_bug.cgi?id=23618
It must be noted that the problem seems to be fixed in recent compiler, but CircleCI uses a compiler that is busted. The reason I did not go the bug repport road is because I expect this bug to be marked as fixed because it is indeed fixed, but that wouldn't address the CircleCI issue.
Jan 12 2023
parent kdevel <kdevel vogtner.de> writes:
On Thursday, 12 January 2023 at 08:55:50 UTC, deadalnix wrote:
 [...] I expect this bug to be marked as fixed because it is 
 indeed fixed, [...]
``` $ dmd --version DMD64 D Compiler v2.101.1 Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved written by Walter Bright $ cat bug23618.d unittest { ubyte ub; ub = 0x80; ub >>= 1u; assert (ub == 0x40); ushort us; us = 0x8000; us >>= 1u; assert (us == 0x4000); } $ dmd -O -checkaction=context -unittest -main -run bug23618.d 1 modules passed unittests $ dmd -checkaction=context -unittest -main -run bug23618.d bug23618.d(5): [unittest] 192 != 64 1/1 modules FAILED unittests ```
Jan 12 2023
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/11/2023 12:55 PM, Paul Backus wrote:
 If we rewrite deadalnix's example using this equivalence, we get the following 
 code:
 
      ushort ee = 1028;
      ee = cast(ushort)(ee << 5U);
      ee = cast(ushort)(ee >> 5U);
      writeln(ee);
 
 ...which prints 1028. So the behavior of the original example is unambiguously
a 
 violation of the language spec.
That's right. It also happens for ubyte operations.
Jan 11 2023
parent reply Salih Dincer <salihdb hotmail.com> writes:
On Wednesday, 11 January 2023 at 23:22:04 UTC, Walter Bright 
wrote:
 On 1/11/2023 12:55 PM, Paul Backus wrote:
 If we rewrite deadalnix's example using this equivalence, we 
 get the following code:
 
      ushort ee = 1028;
      ee = cast(ushort)(ee << 5U);
      ee = cast(ushort)(ee >> 5U);
      writeln(ee);
 
 ...which prints 1028. So the behavior of the original example 
 is unambiguously a violation of the language spec.
That's right. It also happens for ubyte operations.
```d ubyte u = 128; u.writef!"%08b: "; writeln(u); typeof(u >> 1U).stringof.writeln; u >>= 1U; u.writef!"%08b: "; writeln(u); byte b = -128; b.writef!"%08b: "; writeln(b); typeof(b >> 1U).stringof.writeln; b >>= 1U; b.writef!"%08b: "; writeln(b); ``` The problem is that it shift via int first. Then the type is converted to whatever it is, right? I think there is no error because >>> should be used instead of >> ```d u >>>= 1U; assert( u == 64 ); ``` SDB 79
Jan 11 2023
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 1/11/23 15:54, Salih Dincer wrote:

 The problem is that it shift via int first.
Yes but it shouldn't because one of the operands is uint and the 'int' operand should be converted to uint and the operation should have uint semantics.
 I think there is no error
This is a bug because the >> operator should not perform sign extension for unsigned types.
 because >>> should
 be used instead of >>
 could be used but it is the same as >> operator for unsigned types.
import std; void main() { int i = 0x8000_0000; assert(i >> 31 == 0xffff_ffff); // sign extended assert(i >>> 31 == 0x0000_0001); // different for int uint u = 0x8000_0000; assert(u >> 31 == 0x0000_0001); // no extension assert(u >>> 31 == 0x0000_0001); // no difference for uint } Ali
Jan 11 2023
parent Salih Dincer <salihdb hotmail.com> writes:
On Thursday, 12 January 2023 at 04:01:13 UTC, Ali Çehreli wrote:
 On 1/11/23 15:54, Salih Dincer wrote:

 The problem is that it shift via int first.
Yes but it shouldn't because one of the operands is uint and the 'int' operand should be converted to uint and the operation should have uint semantics.
Deadalnix is RIGHT! Interestingly, triple shifting (>>>) does not work correctly on any type, except long! ```d struct TestType(T) { import std.traits : Unsigned; alias U = Unsigned!T; T t = T.min; // sample: -128 for byte U u = U.max/2 + 1; // sample: 128 for ubyte } void main() { alias T = long; // int, short, byte TestType!T v1, v2; enum bits = T.sizeof * 8 - 1; v1.t >>= bits; assert(v1.t == -1); // okay, because signed type v1.u >>= bits; assert(v1.u == 1); // okay, because unsigned type v2.t >>>= bits; assert(v2.t == 1); /* okay, no sign extension but -1 for byte, short, int */ v2.u >>>= bits; assert(v2.u == 1); // okay, no sign extension } ``` SDB 79
Jan 12 2023
prev sibling parent deadalnix <deadalnix gmail.com> writes:
On Wednesday, 11 January 2023 at 13:26:57 UTC, Dukc wrote:
 [The spec 
 says](https://dlang.org/spec/expression.html#shift_expressions) 
 that `>>` means *signed* shift right. `>>>` is for unsigned 
 shifts. So pedantically speaking, 64516 is the correct result.

 It's another issue whether that's good design though. For one, 
 it breaks the rule "do what C does, or don't compile". It'd be 
 more reasonable if `>>` was type-dependant shift right (as in 
 C) IMO.
Signed right shift is the same as logical right shift for unsigned integrals.
Jan 11 2023
prev sibling next sibling parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 1/10/23 17:03, deadalnix wrote:

I am following the code with "Integer Promotions" open:

   https://dlang.org/spec/type.html#integer-promotions

      ushort ee = 1028;
      ee <<= 5U;
      ee >>= 5U;
ee is promoted to 'int' for both operations. 5U is uint. According to documentation above, 'int' should be converted to 'uint'.
 Regular compiler: https://godbolt.org/z/TcbjP76fW (prints 1028)
 Circle CI: 64516 .

 Someone, the compiler manages to do a signed arithmetic shift on an
 unsigned.
I agree, this is a bug. Ali
Jan 11 2023
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
https://github.com/dlang/dmd/pull/14814
Jan 14 2023