https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118777
Bug ID: 118777 Summary: False positive when extending lifetime of temporary containing reference, created by non-static member function [-Wdangling-reference] Product: gcc Version: 15.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: haining.cpp at gmail dot com Target Milestone: --- Created attachment 60405 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=60405&action=edit MRE to produce dangling reference warning gcc version 15.0.1 20250206 (experimental) (Compiler-Explorer-Build-gcc-9a409f5c862c44445b2625c4b94145031394ef28-binutils-2.42) Configured with: ../gcc-trunk-20250206/configure --prefix=/opt/compiler-explorer/gcc-build/staging --enable-libstdcxx-backtrace=yes --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --disable-bootstrap --enable-multiarch --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --enable-clocale=gnu --enable-languages=c,c++,fortran,ada,objc,obj-c++,go,d,rust,m2 --enable-ld=yes --enable-gold=yes --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-linker-build-id --enable-lto --enable-plugins --enable-threads=posix --with-pkgversion=Compiler-Explorer-Build-gcc-9a409f5c862c44445b2625c4b94145031394ef28-binutils-2.42 I can reproduce this on 13.3 and 14.2, but not on 12.4 This program: 1. Creates a `Widget` 1. Creates a temporary callable `Wrapper` 1. Invokes `Wrapper::call` on the `Widget`, which creates and returns a `Holder` with an lvalue reference to the `Widget` 1. Extends the lifetime of the `Holder` with a `const Holder&` in the caller. ``` struct Widget{}; struct Holder { Widget& data; }; struct Wrapper { Holder call(Widget& w) const { return {w}; } }; int main() { Widget w; const Holder& r = Wrapper{}.call(w); (void)r; } ``` ``` $ g++ -Wall -Wextra -pedantic-errors -std=c++17 source.cpp <source>: In function 'int main()': <source>:16:17: warning: possibly dangling reference to a temporary [-Wdangling-reference] 16 | const Holder& r = Wrapper{}.call(w); | ^ <source>:16:21: note: 'Wrapper' temporary created here 16 | const Holder& r = Wrapper{}.call(w); | ``` The warning reads like gcc thinks I'm binding a reference to the `Wrapper` object itself. There are many changes that cause the warning to go away: 1. Remove the reference from `Holder`: struct Holder { Widget data; };` 1. Mark `Wrapper::call` as `static` ``` struct Wrapper { static Holder call(Widget& w) { return {w}; } }; 1. Change main to not bind a reference to the `Holder`: `Holder r = Wrapper{}.call(w);` If `Wrapper::call` constructed `Holder` with a data member or local variable, then this would of course be a dangling reference, but as-written I don't see how it could be since the argument is a non-const lvalue reference. There's also versions of this that actually *do* create a dangling reference, but that do not trigger any warning: ``` struct Widget{}; struct Holder { Widget& data; }; struct Wrapper { Holder call(Widget w) const { // no & return {w}; // returning Holder with reference to local } }; int main() { Widget w; Holder r = Wrapper{}.call(w); // r.data is dangling (void)r; } ``` https://godbolt.org/z/eehbY45o5