From 25475d10573f8075f68c7025057ae99756c7cc0d Mon Sep 17 00:00:00 2001 From: Sami Ahmed Date: Sun, 26 Apr 2026 18:34:38 -0700 Subject: [PATCH] Fix C++20 build: allocators + bundled LevelDB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit C++20 broke two things in the prior bump: 1. std::allocator no longer exposes pointer/const_pointer/reference/ const_reference member typedefs, and the 2-arg allocate(n, hint) was removed. Both secure_allocator and zero_after_free_allocator inherited these from std::allocator. Define the typedefs ourselves and switch the secure_allocator allocate() to the single-arg form. 2. Bundled src/leveldb uses `std::memory_order::memory_order_relaxed` which was valid in C++17 but became a hard error in C++20 (memory_order is now a scoped enum class — the values are at namespace scope or memory_order::relaxed, not memory_order::memory_order_relaxed). LevelDB itself only needs C++11, so pin its targets to C++17 in BuildLevelDB.cmake instead of patching vendored code. Co-Authored-By: Claude Opus 4.7 (1M context) --- cmake/BuildLevelDB.cmake | 14 ++++++++++++++ src/allocators.h | 40 +++++++++++++++++++++------------------- 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/cmake/BuildLevelDB.cmake b/cmake/BuildLevelDB.cmake index 2fff806..2b95e18 100644 --- a/cmake/BuildLevelDB.cmake +++ b/cmake/BuildLevelDB.cmake @@ -9,6 +9,20 @@ if(NOT TARGET leveldb_lib) add_subdirectory("${LEVELDB_SOURCE_DIR}" "${LEVELDB_BINARY_DIR}") endif() +# Pin bundled LevelDB to C++17. It only needs C++11 (declared via its own +# target_compile_features) but inherits CMAKE_CXX_STANDARD=20 from the +# top-level project, where some of its atomic-enum syntax +# (std::memory_order::memory_order_relaxed) becomes a hard error. +foreach(_leveldb_target leveldb_lib leveldb_memenv) + if(TARGET ${_leveldb_target}) + set_target_properties(${_leveldb_target} PROPERTIES + CXX_STANDARD 17 + CXX_STANDARD_REQUIRED ON + CXX_EXTENSIONS OFF + ) + endif() +endforeach() + if(NOT TARGET build_leveldb) add_custom_target(build_leveldb DEPENDS leveldb_lib leveldb_memenv) endif() diff --git a/src/allocators.h b/src/allocators.h index b416e4d..0795817 100644 --- a/src/allocators.h +++ b/src/allocators.h @@ -182,15 +182,17 @@ private: template struct secure_allocator : public std::allocator { - // MSVC8 default copy constructor is broken + // C++20 removed pointer/reference/etc. member typedefs from std::allocator + // and removed the 2-arg allocate(n, hint). Define what we still need + // directly instead of pulling from base. typedef std::allocator base; - typedef typename base::size_type size_type; - typedef typename base::difference_type difference_type; - typedef typename base::pointer pointer; - typedef typename base::const_pointer const_pointer; - typedef typename base::reference reference; - typedef typename base::const_reference const_reference; - typedef typename base::value_type value_type; + typedef T value_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; secure_allocator() throw() {} secure_allocator(const secure_allocator& a) throw() : base(a) {} template @@ -199,10 +201,9 @@ struct secure_allocator : public std::allocator template struct rebind { typedef secure_allocator<_Other> other; }; - T* allocate(std::size_t n, const void *hint = 0) + T* allocate(std::size_t n) { - T *p; - p = std::allocator::allocate(n, hint); + T* p = std::allocator::allocate(n); if (p != NULL) LockedPageManager::instance.LockRange(p, sizeof(T) * n); return p; @@ -226,15 +227,16 @@ struct secure_allocator : public std::allocator template struct zero_after_free_allocator : public std::allocator { - // MSVC8 default copy constructor is broken + // C++20 removed pointer/reference/etc. member typedefs from std::allocator. + // Define what we still need directly instead of pulling from base. typedef std::allocator base; - typedef typename base::size_type size_type; - typedef typename base::difference_type difference_type; - typedef typename base::pointer pointer; - typedef typename base::const_pointer const_pointer; - typedef typename base::reference reference; - typedef typename base::const_reference const_reference; - typedef typename base::value_type value_type; + typedef T value_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; zero_after_free_allocator() throw() {} zero_after_free_allocator(const zero_after_free_allocator& a) throw() : base(a) {} template