memory.h: Force inlining of MaxAlignedAllocable operators Fix -Wmismatched-new-delete warnings in average_blend_test by ensuring the custom new/delete operators are always inlined. This addresses a false positive where the compiler might see a mismatched allocation/deallocation pair due to partial inlining (-Wmismatched-new-delete). Change-Id: Ie4c814a93984200c010770363799ceb97eb5cad9
diff --git a/src/utils/memory.h b/src/utils/memory.h index d2743a3..a91200e 100644 --- a/src/utils/memory.h +++ b/src/utils/memory.h
@@ -29,6 +29,8 @@ #include <memory> #include <new> +#include "src/utils/compiler_attributes.h" + namespace libgav1 { enum { @@ -174,37 +176,50 @@ // A variant of Allocable that forces allocations to be aligned to // kMaxAlignment bytes. This is intended for use with classes that use // alignas() with this value. +// Note when building the source as C++17 or greater, gcc 11.2.0 may issue a +// warning of the form: +// warning: 'void operator delete [](void*, std::align_val_t)' called on +// pointer returned from a mismatched allocation function +// note: returned from 'static void* +// libgav1::MaxAlignedAllocable::operator new [](size_t)' +// This is a false positive and is due to unbalanced inlining of the functions, +// so we force them to be inlined. +// See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103993 struct MaxAlignedAllocable { // Class-specific allocation functions. static void* operator new(size_t size) = delete; static void* operator new[](size_t size) = delete; // Class-specific non-throwing allocation functions - static void* operator new(size_t size, const std::nothrow_t& tag) noexcept { + static LIBGAV1_ALWAYS_INLINE void* operator new( + size_t size, const std::nothrow_t& tag) noexcept { if (size > 0x40000000) return nullptr; return ::operator new(size, std::align_val_t(kMaxAlignment), tag); } - static void* operator new[](size_t size, const std::nothrow_t& tag) noexcept { + static LIBGAV1_ALWAYS_INLINE void* operator new[]( + size_t size, const std::nothrow_t& tag) noexcept { if (size > 0x40000000) return nullptr; return ::operator new[](size, std::align_val_t(kMaxAlignment), tag); } // Class-specific deallocation functions. - static void operator delete(void* ptr) noexcept { + static LIBGAV1_ALWAYS_INLINE void operator delete(void* ptr) noexcept { ::operator delete(ptr, std::align_val_t(kMaxAlignment)); } - static void operator delete[](void* ptr) noexcept { + static LIBGAV1_ALWAYS_INLINE void operator delete[](void* ptr) noexcept { ::operator delete[](ptr, std::align_val_t(kMaxAlignment)); } // Only called if new (std::nothrow) is used and the constructor throws an // exception. - static void operator delete(void* ptr, const std::nothrow_t& tag) noexcept { + static LIBGAV1_ALWAYS_INLINE void operator delete( + void* ptr, const std::nothrow_t& tag) noexcept { ::operator delete(ptr, std::align_val_t(kMaxAlignment), tag); } // Only called if new[] (std::nothrow) is used and the constructor throws an // exception. - static void operator delete[](void* ptr, const std::nothrow_t& tag) noexcept { + static LIBGAV1_ALWAYS_INLINE void operator delete[]( + void* ptr, const std::nothrow_t& tag) noexcept { ::operator delete[](ptr, std::align_val_t(kMaxAlignment), tag); } };