https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84411

            Bug ID: 84411
           Summary: Missed optimization: static guard variable generated
                    for empty virtual destructor
           Product: gcc
           Version: 8.0.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: arthur.j.odwyer at gmail dot com
  Target Milestone: ---

Consider the following program:

struct Base {
    constexpr Base() = default;
    virtual int foo();
    // virtual ~Base() = default;
};
struct Derived : public Base {
    constexpr Derived() = default;
    virtual int foo() override;
};
Base& get_base() {
    static Derived d;
    return d;
}

This is a simplified version of the current idioms around `std::error_category`
and `std::pmr::memory_resource`, except that for now I have commented-out the
virtual destructor.
Notice that because `Derived d` is trivially destructible, no atomic guard
variable is generated to register its destructor with __cxa_atexit.

Now uncomment the defaulted virtual destructor of `Base`. The semantics of
`Derived d` have not changed: we are still expecting to call ~Derived by
non-virtual dispatch, and ~Derived is still known statically to be a no-op. But
now suddenly GCC decides to generate an atomic guard variable and a call to
`__cxa_atexit`!

I think GCC could do better here, and if it did, it would eliminate a lot of
atomic instructions in the critical path for things like `std::error_code{}`
and `std::pmr::new_delete_resource()`.

Reply via email to