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