I have encountered a very strange (apparent) error related to the use of std.typecons' nullable and unions. I appear to be able to clobber the immediately preceding stack variable to a function call if that function makes use of an implicit cast from a nullable wrapped struct to the unwrapped struct where the struct contains a union type which contains an array. Sorry for how strange these requirements are, but I cannot seem to replicate the issue without all of these. See this code:
// Arbitrary union with at least one array member.
union MyUnion
{
int[] _array;
}
// Struct with the above union and at least one other member.
struct MyStruct
{
private int _int; // required (for some reason)
private MyUnion _MyUnion;
}
void main()
{
import std.stdio : writefln;
// setting local `myLocal' to something not null and then invoking
// my method (defined below) `clobber' appears to set the value to
// null.
string myLocal = "NOT NULL";
writefln("myLocal (before clobber): `%s'.", myLocal);
clobber();
writefln("myLocal (after clobber): `%s'.", myLocal);
}
MyStruct clobber()
{
import std.typecons : nullable;
// create a new struct and return it.
// Must use the implicit cast. Using `.get' doesn't induce the bug
auto ret = nullable(MyStruct());
return ret;
}
The output of this program when compiled under ldc2 is:
myLocal (before clobber): `NOT NULL'.
myLocal (after clobber): `'.
Oddly enough, for -O1
and above, the output is the more correct:
myLocal (before clobber): `NOT NULL'.
myLocal (after clobber): `NOT NULL'.
(of note, for -O1
but not -O0
or -O2
and above, the program terminates with a SIGSEV)
Further, when compiled by GDC, the output appears correct.
I'm running all of this on Debian Buster and the below is the output of my ldc2 --version
:
LDC - the LLVM D compiler (1.12.0):
based on DMD v2.082.1 and LLVM 6.0.1
built with LDC - the LLVM D compiler (1.12.0)
Default target: x86_64-pc-linux-gnu
Host CPU: ivybridge
http://dlang.org - http://wiki.dlang.org/LDC
Registered Targets:
aarch64 - AArch64 (little endian)
aarch64_be - AArch64 (big endian)
amdgcn - AMD GCN GPUs
arm - ARM
arm64 - ARM64 (little endian)
armeb - ARM (big endian)
avr - Atmel AVR Microcontroller
bpf - BPF (host endian)
bpfeb - BPF (big endian)
bpfel - BPF (little endian)
hexagon - Hexagon
lanai - Lanai
mips - Mips
mips64 - Mips64 [experimental]
mips64el - Mips64el [experimental]
mipsel - Mipsel
msp430 - MSP430 [experimental]
nvptx - NVIDIA PTX 32-bit
nvptx64 - NVIDIA PTX 64-bit
ppc32 - PowerPC 32
ppc64 - PowerPC 64
ppc64le - PowerPC 64 LE
r600 - AMD GPUs HD2XXX-HD6XXX
sparc - Sparc
sparcel - Sparc LE
sparcv9 - Sparc V9
systemz - SystemZ
thumb - Thumb
thumbeb - Thumb (big endian)
wasm32 - WebAssembly 32-bit
wasm64 - WebAssembly 64-bit
x86 - 32-bit X86: Pentium-Pro and above
x86-64 - 64-bit X86: EM64T and AMD64
xcore - XCore
Am I crazy? Or is this a compiler bug?
Any and all assistance would be much appreciated.