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

            Bug ID: 117913
           Summary: destroying delete operator should have implicit
                    expection speciification
           Product: gcc
           Version: 15.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: alisdairm at me dot com
  Target Milestone: ---

According to [except.spec] 14.5p9, "A deallocation function (6.7.6.5.3) with no
explicit noexcept-specifier has a non-throwing exception specification."

According to the xref (6.7.6.5.3), destroying delete is a deallocation
function, so should have an implicit `noexcept(true)` where no exception
specification is provided.

The following test program verifies all permutations, and gcc fails for only
the case of the implicit exception specification.

Note that when there is a destroying delete, the destructor for the class is
*not* called as part of the delete expression, so the throwing destructor in
the example is there to confirm other behavior that GCC handles correctly.


#include <cstdio>
#include <new>

struct Implicit {
    ~Implicit() noexcept(false) {}

    void operator delete(Implicit*, std::destroying_delete_t) {
        std::puts("destroyed implicit");
    }
};

struct Explicit {
    ~Explicit() noexcept(false) {}

    void operator delete(Explicit*, std::destroying_delete_t) noexcept {
        std::puts("destroyed explicit");
    }
};

struct Undefined {
    ~Undefined() noexcept(false) {}

    void operator delete(Undefined*, std::destroying_delete_t) noexcept(false)
{
        std::puts("destroyed UB");
        throw 42;
    }
};

Implicit * pn = nullptr;
static_assert( noexcept(delete(pn)));

Explicit * qn = nullptr;
static_assert( noexcept(delete(qn)));

Undefined * un = nullptr;
static_assert(!noexcept(delete(un)));

int main() {
    Implicit *p = new Implicit();
    delete p;

    Explicit *q = new Explicit();
    delete q;

    try {
       Undefined *u = new Undefined();
       delete u;
    }
    catch (...) {
         std::puts("undefined behavior");       
    }
}

Reply via email to