https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119978
Bug ID: 119978 Summary: False positive Wdangling-pointer on intrusive list implementatino Product: gcc Version: 15.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- This is a reduced implementation of an intrusive list, similar to how boost::intrusive_list works: struct ListNode { ListNode() = default; ListNode(ListNode&& rhs) noexcept : prev(rhs.prev) , next(rhs.next) { rhs.prev = nullptr; rhs.next = nullptr; if (linked()) { prev->next = this; next->prev = this; } } auto linked() const -> bool { return prev; } auto unlink() -> void { prev->next = next; next->prev = prev; prev = nullptr; next = nullptr; } ListNode* prev = nullptr; ListNode* next = nullptr; }; struct ListAutoLink : ListNode { ListAutoLink() = default; ListAutoLink(ListAutoLink&&) = default; ~ListAutoLink() { if (linked()) { unlink(); } } }; struct Handle : public ListAutoLink { int v; Handle(int v) : v(v) { } }; struct Scheduler { struct IntrusiveList { ListNode node; IntrusiveList() { node.next = &node; node.prev = &node; } auto push_back(Handle& handle) -> void { ListNode& cur = handle; cur.next = &node; cur.prev = node.prev; node.prev->next = &cur; node.prev = &cur; } }; IntrusiveList active_handles_; auto make_handle(int v) -> Handle { auto h = Handle(v); active_handles_.push_back(h); return h; } struct Wrapped { Handle h; }; auto make_wrapped_handle(int v) -> Wrapped { Handle h = make_handle(v); return {.h=(Handle&&)h}; } }; int main() { Scheduler s; auto h1 = s.make_wrapped_handle(1); auto h2 = s.make_wrapped_handle(2); // make sure nothing is dangling ListNode* a = s.active_handles_.node.next; ListNode* b = a->next; ListNode* c = b->next; return (a == &h1.h and b == &h2.h and c == &s.active_handles_.node) ? 0 : 1; } gcc 14.2 -std=c++20 -Wall -O1, this gives a Wdangling-pointer warning here: <source>:58:23: warning: storing the address of local variable 'h' in '*(Scheduler::IntrusiveList*)this.Scheduler::IntrusiveList::node.ListNode::prev' [-Wdangling-pointer=] 58 | node.prev = &cur; | ~~~~~~~~~~^~~~~~ But nothing actually dangles. This program nevertheless returns 0, the move constructor of Handle rebinds the pointers to make sure that it works. This is the best I could reduce it. Further reductions still emit the warning on gcc 14.2 but no longer on gcc 15.1 (e.g. Handle inheriting directly from ListNode instead of ListAutoLink), so there have been some improvements in this area, but this particular one still warns.