https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102168
Bug ID: 102168 Summary: -Wnon-virtual-dtor shouldn't fire for protected dtor in a class with a friend declaration Product: gcc Version: 11.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: i at maskray dot me Target Milestone: --- class base; class b { public: void del(base *x); }; class base { friend b; public: virtual void anchor(); protected: virtual // why is this needed? ~base() = default; }; class derived final : public base { public: ~derived() {} }; void b::del(base *x) { delete x; } % g++ -c -Wnon-virtual-dtor a.cc a.cc:8:7: warning: ‘class base’ has virtual functions and accessible non-virtual destructor [-Wnon-virtual-dtor] 8 | class base { | ^~~~ a.cc:17:7: warning: base class ‘class base’ has accessible non-virtual destructor [-Wnon-virtual-dtor] 17 | class derived final : public base { | ^~~~~~~ This diagnostic is due to a friend declaration because technically the friend can invoke the dtor. However, this seems a bit dumb (https://reviews.llvm.org/rG4852c770fe87) It just checks the existence of friend, not actually checking whether the dtor is actually used. Checking whether the dtor is actually needed requires dataflow analysis (like frontend devirtualization), which is apparently too heavy and may not fit into a compiler diagnostic. In addition, if the friend class ever uses the dtor, it'd trigger -Wdelete-non-virtual-dtor. Now to suppress the diagnostic, we have to add a `virtual`, wasting 2 entries in the vtable and emitting unneeded D0/D2.