This is a result of triaging bug 1559315, it looks like GCC 8.0.1 is miscompiling some code in the LLVM MIPS backend. Here is a minimized test case that reproduces with gcc-8.0.1-0.19.fc29 (I expect that it reproduces with gcc-8.0.1-0.20.fc29 as well, the original test case definitely does reproduce with 0.20): $ cat min.sh #!/bin/bash set -xe rm -f test testopt g++ test.cpp -o testopt -O2 g++ test.cpp -o test -O0 -g ./testopt ./test $ cat test.cpp #include <initializer_list> #include <iostream> template <typename T> class ArrayRef { public: using size_type = size_t; private: /// The start of the array, in an external buffer. const T *Data = nullptr; /// The number of elements. size_type Length = 0; public: /// Construct an ArrayRef from a std::initializer_list. /*implicit*/ ArrayRef(const std::initializer_list<T> &Vec) : Data(Vec.begin() == Vec.end() ? (T *)nullptr : Vec.begin()), Length(Vec.size()) {} const T &operator[](size_t Index) const { return Data[Index]; } }; int main(int argc, char **argv) { const ArrayRef<int> Foo = {42}; std::cout << "Foo " << Foo[0] << "\n"; return 0; } [$ ./min.sh + rm -f test testopt + g++ test.cpp -o testopt -O2 + g++ test.cpp -o test -O0 -g + ./testopt Foo 0 + ./test Foo 42 As you can see it doesn't return the correct value for Foo[0] when compiling with -O2.
Are you sure this is valid? I'm not a C++ expert, but I think the lifetime extension for const references only applies to declarations, not arguments. This means that the std::initializer_list object no longer exists when operator[] is invoked, and the Data member is a dangling pointer, resulting in undefined behavior.
================================================================= ==2756==ERROR: AddressSanitizer: stack-use-after-scope on address 0x7ffd8c1553c0 at pc 0x000000400e34 bp 0x7ffd8c155380 sp 0x7ffd8c155378 READ of size 4 at 0x7ffd8c1553c0 thread T0 #0 0x400e33 in main /tmp/rh1561373.C:26 #1 0x7fd3a7803009 in __libc_start_main (/lib64/libc.so.6+0x21009) #2 0x400b99 in _start (/tmp/rh1561373+0x400b99) Address 0x7ffd8c1553c0 is located in stack of thread T0 at offset 32 in frame #0 0x400c55 in main /tmp/rh1561373.C:24 This frame has 3 object(s): [32, 36) '<unknown>' <== Memory access at offset 32 is inside this variable [96, 112) 'Foo' [160, 176) '<unknown>' HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext (longjmp and C++ exceptions *are* supported) SUMMARY: AddressSanitizer: stack-use-after-scope /tmp/rh1561373.C:26 in main Shadow bytes around the buggy address: 0x100031822a20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x100031822a30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x100031822a40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x100031822a50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x100031822a60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =>0x100031822a70: 00 00 00 00 f1 f1 f1 f1[f8]f2 f2 f2 f2 f2 f2 f2 0x100031822a80: 00 00 f2 f2 f2 f2 f2 f2 f8 f8 f2 f2 f3 f3 f3 f3 0x100031822a90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x100031822aa0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x100031822ab0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x100031822ac0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==2756==ABORTING says g++ -fsanitize=address -g on this. The std::initializer_list object {42} ends lifetime at the end of const ArrayRef<int> Foo = {42}; but the ctor stores a pointer into it and you then access it when it is already out of scope.