<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - Missed optimization: static guard variable generated for empty virtual destructor"
   href="https://bugs.llvm.org/show_bug.cgi?id=36591">36591</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>Missed optimization: static guard variable generated for empty virtual destructor
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>new-bugs
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>trunk
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>All
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>All
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>enhancement
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>new bugs
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>arthur.j.odwyer@gmail.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre>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 guard its construction with
__cxa_guard_acquire/__cxa_guard_release.

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.
(And Derived has a vtable either way, too.) But now suddenly Clang decides to
generate an atomic guard variable!

I think Clang 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()`.

(Slightly different symptom, same bug, filed as
<a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84411">https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84411</a> .)</pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>