https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106174
Bug ID: 106174 Summary: c++20: compilation fails erroneously with "deallocation of already deallocated storage" Product: gcc Version: 12.1.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: janpmoeller at gmx dot de Target Milestone: --- The following c++20 source fails to compile on gcc 12.1 and current trunk: //////////////////////////////////////////////////////////////////////////////// #include <array> #include <memory> struct test_vector { constexpr ~test_vector() noexcept { m_allocator.deallocate(m_begin, m_capacity); } constexpr test_vector(std::size_t n) : m_begin(m_allocator.allocate(n)) , m_capacity(n) { } constexpr test_vector(test_vector const& other) : test_vector(other.m_capacity) { } constexpr test_vector() = delete; constexpr test_vector(test_vector&& other) noexcept = delete; constexpr auto operator=(test_vector const& other) -> test_vector& = delete; constexpr auto operator=(test_vector&& other) noexcept -> test_vector& = delete; std::allocator<int> m_allocator{}; int* m_begin; std::size_t m_capacity; }; static_assert( // This fails with "deallocation of already deallocated storage" [] { std::array<test_vector, 1> const values{test_vector(42)}; std::array<test_vector, 1> const copy = values; return true; }()); //////////////////////////////////////////////////////////////////////////////// The compiler outputs: <source>:46:6: error: non-constant condition for static assertion 41 | [] | ~~ 42 | { | ~ 43 | std::array<test_vector, 1> const values{test_vector(42)}; | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 44 | std::array<test_vector, 1> const copy = values; | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 45 | return true; | ~~~~~~~~~~~~ 46 | }()); | ~^~ In file included from /opt/compiler-explorer/gcc-trunk-20220703/include/c++/13.0.0/memory:64, from <source>:2: <source>:46:6: in 'constexpr' expansion of '<lambda closure object><lambda()>().<lambda()>()' <source>:46:5: in 'constexpr' expansion of '((std::array<test_vector, 1>*)(& copy))->std::array<test_vector, 1>::~array()' /opt/compiler-explorer/gcc-trunk-20220703/include/c++/13.0.0/array:94:12: in 'constexpr' expansion of '<anonymous>->test_vector::~test_vector()' <source>:8:31: in 'constexpr' expansion of '((test_vector*)this)->test_vector::m_allocator.std::allocator<int>::deallocate(((test_vector*)this)->test_vector::m_begin, ((test_vector*)this)->test_vector::m_capacity)' /opt/compiler-explorer/gcc-trunk-20220703/include/c++/13.0.0/bits/allocator.h:202:30: error: deallocation of already deallocated storage 202 | ::operator delete(__p); | ~~~~~~~~~~~~~~~~~^~~~~ Compiler returned: 1 Weirdly, the usage of std::array seems to be important here. I was unable to reproduce this without the std::array. For example, the following variants compile just fine: // 1) This is accepted test_vector const values(42); test_vector const copy = values; // 2) This is accepted test_vector const values(42); std::array<test_vector, 1> const copy = {values}; // 3) This is accepted std::array<test_vector, 1> const values{test_vector(42)}; test_vector const copy = values[0]; The above test case is also available on compiler explorer: https://godbolt.org/z/6xvx4fx6E