From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id 3EF5E3858C98; Tue, 5 Mar 2024 20:08:40 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 3EF5E3858C98 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1709669320; bh=PvlpQ7Oh101VvyzzOL6rbEGiMfPsynYAw64EmKcun2E=; h=From:To:Subject:Date:From; b=DThXgI/AN6NcvvE49qxuJgLF8oOkg29duhA4NYCkDbUmHl6+E5CBt339qZ3TZHTZh SZpMrrhgADMJhDFCOaEOAkk44Hr4/S+WV9V2R1HqkVbusgiUJ1aESOJLx/E79PTF4N iwiK+dtPei5xGvsciElL4fTuFeCInnYX1bdepboU= From: "mwinkler at blizzard dot com" To: gcc-bugs@gcc.gnu.org Subject: [Bug c++/114245] New: Defaulted virtual destructors that do no work overwrite the vtable with `-O0` Date: Tue, 05 Mar 2024 20:08:39 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: new X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: c++ X-Bugzilla-Version: 13.2.0 X-Bugzilla-Keywords: X-Bugzilla-Severity: normal X-Bugzilla-Who: mwinkler at blizzard dot com X-Bugzilla-Status: UNCONFIRMED X-Bugzilla-Resolution: X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: bug_id short_desc product version bug_status bug_severity priority component assigned_to reporter target_milestone Message-ID: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 List-Id: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D114245 Bug ID: 114245 Summary: Defaulted virtual destructors that do no work overwrite the vtable with `-O0` Product: gcc Version: 13.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: mwinkler at blizzard dot com Target Milestone: --- https://godbolt.org/z/Ge135h6qh Use the godbolt for reference against all the 3 major compilers, GCC/Clang/MSVC. The following bug report is only for `-O0` builds. Optimized builds end up removing the dead vtable stores but we require our debug builds to behave the same as release builds. Given a virtual destructor that is defaulted and does no work GCC will overwrite the vtable with the current objects most constructed type. This behaviour isn't required by MSVC or Itanium CXX ABI or the C++ std but= it would be nice to have all 3 major compilers agree here especially since MSVC and Clang both have this behaviour. ``` struct Base { virtual ~Base() =3D default; }; struct Derived : Base { virtual ~Derived() =3D default; }; ``` In the example above `~Derived` will overwrite the vtable with the vtable f= or Derived. `~Base` will overwrite the vtable with the vtable for Base. If you have a global object of `Derived` you easily run into static de-init fiasco issues since these objects are also registered with `__cxa_atexit`. Clang and MSVC for defaulted virtual destructors do not overwrite the vtabl= e in the generated destructors even though they still register with `__cxa_atexi= t` so the running of the destructor ends up being a nop. Clang also has the `[[clang::no_destroy]]` attribute. We have a workaround on GCC by doing the following for such global objects. ``` union NoDestroy { Derived v; constexpr NoDestroy() : v() {} ~NoDestroy() {} }; ``` There are two solutions that will work for our use case. Add a similar attribute like `[[clang::no_destroy]]` to mark certain global objects that should not be registered with `__cxa_atexit`. I couldn't find = such a similar attribute in the GCC docs. Have GCC behave like MSVC and Clang here when optimizations are disabled and have defaulted virtual destructors not overwrite the vtable. Thanks :).=