https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126312
Bug ID: 126312
Summary: Bad ARM64 codegen: mandatory copy elision not enforced
creates dangling reference
Product: gcc
Version: 16.1.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: middle-end
Assignee: unassigned at gcc dot gnu.org
Reporter: gufideg at gmail dot com
Target Milestone: ---
When returning from a function that returns by value using copy elision, it
seems GCC does not enforce copy elision and do copy the object.
struct val_ref {
constexpr val_ref() : val(42), ref(val) {}
val_ref(val_ref&&) = delete;
val_ref(val_ref const&) = delete;
int val;
int& ref;
};
struct wrapper {
constexpr wrapper(): impl{} {}
val_ref impl{};
};
constexpr auto make_s() {
return wrapper{};
}
constexpr int test() {
auto s = make_s();
return s.impl.ref;
}
I tagged it "middle-end" since bad code generation is possible, but it seems
like it's also a front end issue since the constexpr evaluator (on ARM64 only)
will reject the valid code.
//static_assert(test());
int main() {
return test() == 42 ? 0 : 1;
}
This self referential struct is immovable, yet the ARM64 codegen read garbage
bytes.
Uncommenting the static assert, the compiler will refuse to execute the code
claiming `s.impl.ref` is read outside of its lifetime, even though the object
is still alive at this point.
Strangely, this only happen on ARM64. x86-64 and ARM 32 bit compile this code
correctly, and does not diagnose the static assert.
Compiler explorer link: https://godbolt.org/z/7hnbh94b5