Not only global variables can hold references to dead stack variables.
Consider this example:
void write_stack_address_to(char **q) { char local; *q = &local; } void test_stack() { char *p; write_stack_address_to(&p); }
The address of local is assigned to p, which becomes a dangling
pointer after write_stack_address_to() returns.
The StackAddrEscapeChecker was looking for bindings in the store which
referred to variables of the popped stack frame, but it only considered
global variables in this regard. This patch relaxes this, catching
stack variable bindings as well.
This patch also works for temporary objects like:
struct Bar { const int &ref; explicit Bar(int y) : ref(y) { // Okay. } // End of the constructor call, `ref` is dangling now. Warning! }; void test() { Bar{33}; // Temporary object, so the corresponding memregion is // *not* a VarRegion. }
The return value optimization aka. copy-elision might kick in but that
is modeled by passing an imaginary CXXThisRegion which refers to the
parent stack frame which is supposed to be the return slot.
Objects residing in the return slot outlive the scope of the inner
call, thus we should expect no warning about them - except if we
explicitly disable copy-elision.
You probably meant ||?