https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100553
Bug ID: 100553 Summary: [constexpr] new/delete matching fails when ref-counted pointers are stored in arrays Product: gcc Version: 12.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: ldalessandro at gmail dot com Target Milestone: --- Sorry about the complexity of this test case. Consider the following code. ``` #include <memory> struct Node { int count = 0; constexpr virtual void destroy() const = 0; // workaround https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100495 }; struct node_ptr { Node *ptr_; constexpr ~node_ptr() { dec(); } constexpr node_ptr(node_ptr const& b) : ptr_(b.ptr_) { inc(); } constexpr node_ptr(node_ptr&& b) : ptr_(std::exchange(b.ptr_, nullptr)) { } constexpr node_ptr(Node *ptr) : ptr_(ptr) { inc(); } constexpr node_ptr& operator=(Node* b) { if (b) { ++b->count; } dec(); ptr_ = b; return *this; } constexpr void inc() const { if (ptr_) { ++ptr_->count; } } constexpr void dec() { if (ptr_) { if (--ptr_->count == 0) { std::exchange(ptr_, nullptr)->destroy(); } } } }; struct Unary : Node { node_ptr children[1] = { nullptr }; node_ptr a = nullptr; constexpr void destroy() const override { delete this; } }; #ifdef ARRAY // fails #define a(node) node->children[0] #else #define a(node) node->a #endif struct Tree { Unary c; constexpr Tree(node_ptr const& tree) { std::construct_at(&c, static_cast<Unary const&>(*tree.ptr_)); a((&c)) = nullptr; } }; constexpr node_ptr foo() { Unary *node = new Unary; a(node) = new Unary; return node; } constexpr Tree tree = foo(); // error: use of allocated storage after deallocation in a constant expression ``` This is a fragment of some tree code that I'm using and includes a base Node* type with a count for an intrusive node_ptr reference counted pointer. There is one derived type, Unary, that stores a single node_ptr, either as an ARRAY or as a scalar member. The tree stores a single Unary node. There's a macro for the sake of the test case, -DARRAY uses the array member. When I use the array member gcc-trunk fails to match the new/deletes, while its fine with the scalar member. Clang compiles both without error. https://godbolt.org/z/oGc1qTvvo