Thread overview
Weird codegen bug
Jun 13, 2019
RazvanN
Jun 13, 2019
Daniel Kozak
Jun 13, 2019
Dennis
Jun 13, 2019
Radu
Jun 13, 2019
Patrick Schluter
Jun 13, 2019
John Colvin
Jun 13, 2019
RazvanN
Jun 13, 2019
John Colvin
Jun 14, 2019
Walter Bright
June 13, 2019
import std.stdio : writeln;

void main()
{
    int a = 7;
    int b = 9;

    /* some code later */

    *(&a + 1) = 2;
    writeln(b);
    writeln(b);
}

This code prints:

9
2

with latest version of dmd. Is this a bug or am I missing something? For the record,
gdc prints (as expected):

2
2

June 13, 2019
ldc will print
9
9
and sigsegv :D

On Thu, Jun 13, 2019 at 1:30 PM RazvanN via Digitalmars-d < digitalmars-d@puremagic.com> wrote:

> import std.stdio : writeln;
>
> void main()
> {
>      int a = 7;
>      int b = 9;
>
>      /* some code later */
>
>      *(&a + 1) = 2;
>      writeln(b);
>      writeln(b);
> }
>
> This code prints:
>
> 9
> 2
>
> with latest version of dmd. Is this a bug or am I missing
> something? For the record,
> gdc prints (as expected):
>
> 2
> 2
>
>


June 13, 2019
On Thursday, 13 June 2019 at 11:28:25 UTC, RazvanN wrote:
> Is this a bug or am I missing something? For the record,
> gdc prints (as expected):

What happens is that b lives in a register.
After the first call, the register is invalidated and it has to be reloaded with the value on the stack (modified by your pointer).

I'm pretty sure *(&a + 1) = 2; is undefined behavior, so both dmd and gdc are correct.

(Assembly can be seen here: https://run.dlang.io/is/bjxVXg)
June 13, 2019
On Thursday, 13 June 2019 at 11:28:25 UTC, RazvanN wrote:
> import std.stdio : writeln;
>
> void main()
> {
>     int a = 7;
>     int b = 9;
>
>     /* some code later */
>
>     *(&a + 1) = 2;
>     writeln(b);
>     writeln(b);
> }
>
> This code prints:
>
> 9
> 2
>
> with latest version of dmd. Is this a bug or am I missing something? For the record,
> gdc prints (as expected):
>
> 2
> 2

Check out gotbolt output:

https://godbolt.org/z/sxo_8l
June 13, 2019
On Thursday, 13 June 2019 at 11:28:25 UTC, RazvanN wrote:
> import std.stdio : writeln;
>
> void main()
> {
>     int a = 7;
>     int b = 9;
>
>     /* some code later */
>
>     *(&a + 1) = 2;
>     writeln(b);
>     writeln(b);
> }
>
> This code prints:
>
> 9
> 2
>
> with latest version of dmd. Is this a bug or am I missing something? For the record,
> gdc prints (as expected):
>
> 2
> 2

It's definitely not a codegen bug. It's a programmers assumption bug :-)
June 13, 2019
On Thursday, 13 June 2019 at 11:28:25 UTC, RazvanN wrote:
> import std.stdio : writeln;
>
> void main()
> {
>     int a = 7;
>     int b = 9;
>
>     /* some code later */
>
>     *(&a + 1) = 2;
>     writeln(b);
>     writeln(b);
> }
>
> This code prints:
>
> 9
> 2
>
> with latest version of dmd. Is this a bug or am I missing something? For the record,
> gdc prints (as expected):
>
> 2
> 2

Why would you think this should work? Locals are not the same as struct members, you can't just walk a pointer around.
June 13, 2019
On Thursday, 13 June 2019 at 13:45:04 UTC, John Colvin wrote:
> On Thursday, 13 June 2019 at 11:28:25 UTC, RazvanN wrote:
>> import std.stdio : writeln;
>>
>> void main()
>> {
>>     int a = 7;
>>     int b = 9;
>>
>>     /* some code later */
>>
>>     *(&a + 1) = 2;
>>     writeln(b);
>>     writeln(b);
>> }
>>
>> This code prints:
>>
>> 9
>> 2
>>
>> with latest version of dmd. Is this a bug or am I missing something? For the record,
>> gdc prints (as expected):
>>
>> 2
>> 2
>
> Why would you think this should work? Locals are not the same as struct members, you can't just walk a pointer around.

I think it's odd that b changes its value for no apparent reason. I understand why it happens, still it is surprising.
June 13, 2019
On Thursday, 13 June 2019 at 15:42:38 UTC, RazvanN wrote:
> On Thursday, 13 June 2019 at 13:45:04 UTC, John Colvin wrote:
>> On Thursday, 13 June 2019 at 11:28:25 UTC, RazvanN wrote:
>>> import std.stdio : writeln;
>>>
>>> void main()
>>> {
>>>     int a = 7;
>>>     int b = 9;
>>>
>>>     /* some code later */
>>>
>>>     *(&a + 1) = 2;
>>>     writeln(b);
>>>     writeln(b);
>>> }
>>>
>>> This code prints:
>>>
>>> 9
>>> 2
>>>
>>> with latest version of dmd. Is this a bug or am I missing something? For the record,
>>> gdc prints (as expected):
>>>
>>> 2
>>> 2
>>
>> Why would you think this should work? Locals are not the same as struct members, you can't just walk a pointer around.
>
> I think it's odd that b changes its value for no apparent reason. I understand why it happens, still it is surprising.

Undefined behaviour is often surprising.
June 14, 2019
On 6/13/2019 4:28 AM, RazvanN wrote:
> import std.stdio : writeln;
> 
> void main()
> {
>      int a = 7;
>      int b = 9;
> 
>      /* some code later */
> 
>      *(&a + 1) = 2;
>      writeln(b);
>      writeln(b);
> }
> 
> This code prints:
> 
> 9
> 2
> 
> with latest version of dmd. Is this a bug or am I missing something? For the record,
> gdc prints (as expected):
> 
> 2
> 2
> 

It's undefined behavior to access memory beyond the boundaries of the memory object pointed to:

https://github.com/dlang/dlang.org/pull/2649/files#diff-2bcc1b9af1e2da4f63bfda4b26f114a2R90

in an update to the spec that nobody sees fit to pull :-(