https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=7d5c55faa196844260cf6c7e4d51d7e64016ff06
commit 7d5c55faa196844260cf6c7e4d51d7e64016ff06 Author: Jeremy Drake <cyg...@jdrake.com> Date: Fri Jul 25 13:05:30 2025 -0700 Cygwin: add wrappers for newer new/delete overloads A sized delete (with a std::size_t parameter) was added in C++14 (but doesn't combine with nothrow_t) An aligned new/delete (with a std::align_val_t parameter) was added in C++17, and combinations with the sized delete and nothrow_t variants. Signed-off-by: Jeremy Drake <cyg...@jdrake.com> Diff: --- winsup/cygwin/cxx.cc | 120 ++++++++++++++++++++++++++++-- winsup/cygwin/cygwin.din | 12 +++ winsup/cygwin/lib/_cygwin_crt0_common.cc | 59 +++++++++++++++ winsup/cygwin/libstdcxx_wrapper.cc | 99 ++++++++++++++++++++++++ winsup/cygwin/local_includes/cygwin-cxx.h | 14 ++++ 5 files changed, 299 insertions(+), 5 deletions(-) diff --git a/winsup/cygwin/cxx.cc b/winsup/cygwin/cxx.cc index b69524aca..a14aab872 100644 --- a/winsup/cygwin/cxx.cc +++ b/winsup/cygwin/cxx.cc @@ -28,27 +28,75 @@ operator delete (void *p) free (p); } +void * +operator new[] (std::size_t s) +{ + return ::operator new (s); +} + +void +operator delete[] (void *p) +{ + ::operator delete (p); +} + #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wc++14-compat" void operator delete (void *p, size_t) { - ::operator delete(p); + ::operator delete (p); +} + +void +operator delete[] (void *p, size_t) +{ + ::operator delete (p); } #pragma GCC diagnostic pop +/* Aligned versions, provided only for completeness in the fallback array. */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wc++17-compat" void * -operator new[] (std::size_t s) +operator new (std::size_t sz, std::align_val_t al) { - return ::operator new (s); + void *ret; + /* is memset needed here, since the non-aligned version uses calloc? */ + if (!posix_memalign (&ret, static_cast <std::size_t> (al), sz)) + return ret; + return NULL; +} + +void * +operator new[] (std::size_t sz, std::align_val_t al) +{ + return ::operator new (sz, al); } void -operator delete[] (void *p) +operator delete (void *p, std::align_val_t) { - ::operator delete (p); + free (p); +} +void +operator delete[] (void *p, std::align_val_t al) +{ + ::operator delete (p, al); } +void +operator delete (void *p, std::size_t, std::align_val_t al) +{ + ::operator delete (p, al); +} + +void operator delete[] (void *p, std::size_t, std::align_val_t al) +{ + ::operator delete (p, al); +} +#pragma GCC diagnostic pop + /* Nothrow versions, provided only for completeness in the fallback array. */ void * @@ -76,6 +124,51 @@ operator delete[] (void *p, const std::nothrow_t &nt) ::operator delete (p, nt); } +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wc++14-compat" +void +operator delete (void *p, size_t, const std::nothrow_t &nt) +{ + ::operator delete (p, nt); +} + +void +operator delete[] (void *p, size_t, const std::nothrow_t &nt) +{ + ::operator delete (p, nt); +} +#pragma GCC diagnostic pop + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wc++17-compat" +void * +operator new (std::size_t sz, std::align_val_t al, const std::nothrow_t &) +{ + + void *ret; + /* is memset needed here, since the non-aligned version uses calloc? */ + if (!posix_memalign (&ret, static_cast <std::size_t> (al), sz)) + return ret; + return NULL; +} + +void * +operator new[] (std::size_t sz, std::align_val_t al, const std::nothrow_t &nt) +{ + return ::operator new (sz, al, nt); +} + +void +operator delete (void *p, std::align_val_t, const std::nothrow_t &nt) +{ + ::operator delete (p, nt); +} + +void operator delete[] (void *p, std::align_val_t, const std::nothrow_t &nt) +{ + ::operator delete (p, nt); +} +#pragma GCC diagnostic pop extern "C" void __cxa_pure_virtual (void) @@ -95,10 +188,27 @@ struct per_process_cxx_malloc default_cygwin_cxx_malloc = &(operator new[]), &(operator delete), &(operator delete[]), + /* nothrow new/delete */ + &(operator new), + &(operator new[]), + &(operator delete), + &(operator delete[]), + /* C++14 sized delete */ + &(operator delete), + &(operator delete[]), + /* C++17 aligned new/delete */ &(operator new), &(operator new[]), &(operator delete), &(operator delete[]), + /* aligned + sized delete */ + &(operator delete), + &(operator delete[]), + /* aligned + nothrow new/delete */ + &(operator new), + &(operator new[]), + &(operator delete), + &(operator delete[]) }; diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din index d7a17b234..cd71da274 100644 --- a/winsup/cygwin/cygwin.din +++ b/winsup/cygwin/cygwin.din @@ -124,13 +124,25 @@ __swbuf_r SIGFE __vsnprintf_chk SIGFE __vsprintf_chk SIGFE __wrap__ZdaPv NOSIGFE # void operator delete[](void *p) throw() +__wrap__ZdaPvm NOSIGFE # void operator delete[](void *p, std::size_t sz) throw() +__wrap__ZdaPvmSt11align_val_t NOSIGFE # void operator delete[](void *p, std::size_t sz, std::align_val_t al) throw() __wrap__ZdaPvRKSt9nothrow_t NOSIGFE # void operator delete[](void *p, const std::nothrow_t &nt) throw() +__wrap__ZdaPvSt11align_val_t NOSIGFE # void operator delete[](void *p, std::align_val_t al) throw() +__wrap__ZdaPvSt11align_val_tRKSt9nothrow_t NOSIGFE # void operator delete[](void *p, std::align_val_t al, const std::nothrow_t &nt) throw() __wrap__ZdlPv NOSIGFE # void operator delete(void *p) throw() +__wrap__ZdlPvm NOSIGFE # void operator delete(void *p, std::size_t sz) throw() +__wrap__ZdlPvmSt11align_val_t NOSIGFE # void operator delete(void *p, std::size_t sz, std::align_val_t al) throw() __wrap__ZdlPvRKSt9nothrow_t NOSIGFE # void operator delete(void *p, const std::nothrow_t &nt) throw() +__wrap__ZdlPvSt11align_val_t NOSIGFE # void operator delete(void *p, std::align_val_t al) throw() +__wrap__ZdlPvSt11align_val_tRKSt9nothrow_t NOSIGFE # void operator delete(void *p, std::align_val_t al, const std::nothrow_t &nt) throw() __wrap__Znam NOSIGFE # void *operator new[](std::size_t sz) throw (std::bad_alloc) __wrap__ZnamRKSt9nothrow_t NOSIGFE # void *operator new[](std::size_t sz, const std::nothrow_t &nt) throw() +__wrap__ZnamSt11align_val_t NOSIGFE # void *operator new[](std::size_t sz, std::align_val_t al) throw (std::bad_alloc) +__wrap__ZnamSt11align_val_tRKSt9nothrow_t NOSIGFE # void *operator new[](std::size_t sz, std::align_val_t al, const std::nothrow_t &nt) throw() __wrap__Znwm NOSIGFE # void *operator new(std::size_t sz) throw (std::bad_alloc) __wrap__ZnwmRKSt9nothrow_t NOSIGFE # void *operator new(std::size_t sz, const std::nothrow_t &nt) throw() +__wrap__ZnwmSt11align_val_t NOSIGFE # void *operator new(std::size_t sz, std::align_val_t al) throw (std::bad_alloc) +__wrap__ZnwmSt11align_val_tRKSt9nothrow_t NOSIGFE # void *operator new(std::size_t sz, std::align_val al, const std::nothrow_t &nt) throw() __xdrrec_getrec SIGFE __xdrrec_setnonblock SIGFE __xpg_sigpause SIGFE diff --git a/winsup/cygwin/lib/_cygwin_crt0_common.cc b/winsup/cygwin/lib/_cygwin_crt0_common.cc index d356a50fb..5900e6315 100644 --- a/winsup/cygwin/lib/_cygwin_crt0_common.cc +++ b/winsup/cygwin/lib/_cygwin_crt0_common.cc @@ -22,6 +22,18 @@ details. */ #define REAL_ZDAPV _SYMSTR (__real__ZdaPv) #define REAL_ZDLPV_NOTHROW_T _SYMSTR (__real__ZdlPvRKSt9nothrow_t) #define REAL_ZDAPV_NOTHROW_T _SYMSTR (__real__ZdaPvRKSt9nothrow_t) +#define REAL_ZDLPVM _SYMSTR (__real__ZdlPvm) +#define REAL_ZDAPVM _SYMSTR (__real__ZdaPvm) +#define REAL_ZNWX_ALIGN_VAL_T "__real__ZnwmSt11align_val_t" +#define REAL_ZNAX_ALIGN_VAL_T "__real__ZnamSt11align_val_t" +#define REAL_ZDLPV_ALIGN_VAL_T _SYMSTR (__real__ZdlPvSt11align_val_t) +#define REAL_ZDAPV_ALIGN_VAL_T _SYMSTR (__real__ZdaPvSt11align_val_t) +#define REAL_ZDLPVM_ALIGN_VAL_T _SYMSTR (__real__ZdlPvmSt11align_val_t) +#define REAL_ZDAPVM_ALIGN_VAL_T _SYMSTR (__real__ZdaPvmSt11align_val_t) +#define REAL_ZNWX_ALIGN_VAL_T_NOTHROW_T "__real__ZnwmSt11align_val_tRKSt9nothrow_t" +#define REAL_ZNAX_ALIGN_VAL_T_NOTHROW_T "__real__ZnamSt11align_val_tRKSt9nothrow_t" +#define REAL_ZDLPV_ALIGN_VAL_T_NOTHROW_T _SYMSTR (__real__ZdlPvSt11align_val_tRKSt9nothrow_t) +#define REAL_ZDAPV_ALIGN_VAL_T_NOTHROW_T _SYMSTR (__real__ZdaPvSt11align_val_tRKSt9nothrow_t) /* Use asm names to bypass the --wrap that is being applied to redirect all other references to these operators toward the redirectors in the Cygwin DLL; this @@ -43,6 +55,30 @@ extern WEAK void operator delete(void *p, const std::nothrow_t &nt) noexcept (tr __asm__ (REAL_ZDLPV_NOTHROW_T); extern WEAK void operator delete[](void *p, const std::nothrow_t &nt) noexcept (true) __asm__ (REAL_ZDAPV_NOTHROW_T); +extern WEAK void operator delete(void *p, std::size_t sz) noexcept (true) + __asm__ (REAL_ZDLPVM); +extern WEAK void operator delete[](void *p, std::size_t sz) noexcept (true) + __asm__ (REAL_ZDAPVM); +extern WEAK void *operator new(std::size_t sz, std::align_val_t al) noexcept (false) + __asm__ (REAL_ZNWX_ALIGN_VAL_T); +extern WEAK void *operator new[](std::size_t sz, std::align_val_t al) noexcept (false) + __asm__ (REAL_ZNAX_ALIGN_VAL_T); +extern WEAK void operator delete(void *p, std::align_val_t al) noexcept (true) + __asm__ (REAL_ZDLPV_ALIGN_VAL_T); +extern WEAK void operator delete[](void *p, std::align_val_t al) noexcept (true) + __asm__ (REAL_ZDAPV_ALIGN_VAL_T); +extern WEAK void operator delete(void *p, std::size_t sz, std::align_val_t al) noexcept (true) + __asm__ (REAL_ZDLPVM_ALIGN_VAL_T); +extern WEAK void operator delete[](void *p, std::size_t sz, std::align_val_t al) noexcept (true) + __asm__ (REAL_ZDAPVM_ALIGN_VAL_T); +extern WEAK void *operator new(std::size_t sz, std::align_val_t al, const std::nothrow_t &nt) noexcept (true) + __asm__ (REAL_ZNWX_ALIGN_VAL_T_NOTHROW_T); +extern WEAK void *operator new[](std::size_t sz, std::align_val_t al, const std::nothrow_t &nt) noexcept (true) + __asm__ (REAL_ZNAX_ALIGN_VAL_T_NOTHROW_T); +extern WEAK void operator delete(void *p, std::align_val_t al, const std::nothrow_t &nt) noexcept (true) + __asm__ (REAL_ZDLPV_ALIGN_VAL_T_NOTHROW_T); +extern WEAK void operator delete[](void *p, std::align_val_t al, const std::nothrow_t &nt) noexcept (true) + __asm__ (REAL_ZDAPV_ALIGN_VAL_T_NOTHROW_T); /* Avoid an info message from linker when linking applications. */ extern __declspec(dllimport) struct _reent *_impure_ptr; @@ -65,6 +101,17 @@ struct per_process_cxx_malloc __cygwin_cxx_malloc = { &(operator new), &(operator new[]), &(operator delete), &(operator delete[]), + /* nothrow new/delete */ + &(operator new), &(operator new[]), + &(operator delete), &(operator delete[]), + /* C++14 sized delete */ + &(operator delete), &(operator delete[]), + /* C++17 aligned new/delete */ + &(operator new), &(operator new[]), + &(operator delete), &(operator delete[]), + /* aligned + sized delete */ + &(operator delete), &(operator delete[]), + /* aligned + nothrow new/delete */ &(operator new), &(operator new[]), &(operator delete), &(operator delete[]) }; @@ -143,6 +190,18 @@ _cygwin_crt0_common (MainFunc f, per_process *u) CONDITIONALLY_OVERRIDE(oper_new___nt); CONDITIONALLY_OVERRIDE(oper_delete_nt); CONDITIONALLY_OVERRIDE(oper_delete___nt); + CONDITIONALLY_OVERRIDE(oper_delete_sz); + CONDITIONALLY_OVERRIDE(oper_delete___sz); + CONDITIONALLY_OVERRIDE(oper_new_al); + CONDITIONALLY_OVERRIDE(oper_new___al); + CONDITIONALLY_OVERRIDE(oper_delete_al); + CONDITIONALLY_OVERRIDE(oper_delete___al); + CONDITIONALLY_OVERRIDE(oper_delete_sz_al); + CONDITIONALLY_OVERRIDE(oper_delete___sz_al); + CONDITIONALLY_OVERRIDE(oper_new_al_nt); + CONDITIONALLY_OVERRIDE(oper_new___al_nt); + CONDITIONALLY_OVERRIDE(oper_delete_al_nt); + CONDITIONALLY_OVERRIDE(oper_delete___al_nt); /* Now update the resulting set into the global redirectors. */ *newu->cxx_malloc = __cygwin_cxx_malloc; } diff --git a/winsup/cygwin/libstdcxx_wrapper.cc b/winsup/cygwin/libstdcxx_wrapper.cc index 34911d0e1..fa13fddc9 100644 --- a/winsup/cygwin/libstdcxx_wrapper.cc +++ b/winsup/cygwin/libstdcxx_wrapper.cc @@ -24,6 +24,10 @@ details. */ #define MANGLED_ZNAX "__wrap__Znam" #define MANGLED_ZNWX_NOTHROW_T "__wrap__ZnwmRKSt9nothrow_t" #define MANGLED_ZNAX_NOTHROW_T "__wrap__ZnamRKSt9nothrow_t" +#define MANGLED_ZNWX_ALIGN_VAL_T "__wrap__ZnwmSt11align_val_t" +#define MANGLED_ZNAX_ALIGN_VAL_T "__wrap__ZnamSt11align_val_t" +#define MANGLED_ZNWX_ALIGN_VAL_T_NOTHROW_T "__wrap__ZnwmSt11align_val_tRKSt9nothrow_t" +#define MANGLED_ZNAX_ALIGN_VAL_T_NOTHROW_T "__wrap__ZnamSt11align_val_tRKSt9nothrow_t" extern void *operator new(std::size_t sz) noexcept (false) __asm__ (MANGLED_ZNWX); @@ -41,6 +45,30 @@ extern void operator delete(void *p, const std::nothrow_t &nt) noexcept (true) __asm__ (_SYMSTR (__wrap__ZdlPvRKSt9nothrow_t)); extern void operator delete[](void *p, const std::nothrow_t &nt) noexcept (true) __asm__ (_SYMSTR (__wrap__ZdaPvRKSt9nothrow_t)); +extern void operator delete(void *p, std::size_t sz) noexcept (true) + __asm__ (_SYMSTR (__wrap__ZdlPvm)); +extern void operator delete[](void *p, std::size_t sz) noexcept (true) + __asm__ (_SYMSTR (__wrap__ZdaPvm)); +extern void *operator new(std::size_t sz, std::align_val_t al) noexcept (false) + __asm__ (MANGLED_ZNWX_ALIGN_VAL_T); +extern void *operator new[](std::size_t sz, std::align_val_t al) noexcept (false) + __asm__ (MANGLED_ZNAX_ALIGN_VAL_T); +extern void operator delete(void *p, std::align_val_t al) noexcept (true) + __asm__ (_SYMSTR (__wrap__ZdlPvSt11align_val_t)); +extern void operator delete[](void *p, std::align_val_t al) noexcept (true) + __asm__ (_SYMSTR (__wrap__ZdaPvSt11align_val_t)); +extern void operator delete(void *p, std::size_t sz, std::align_val_t al) noexcept (true) + __asm__ (_SYMSTR (__wrap__ZdlPvmSt11align_val_t)); +extern void operator delete[](void *p, std::size_t sz, std::align_val_t al) noexcept (true) + __asm__ (_SYMSTR (__wrap__ZdaPvmSt11align_val_t)); +extern void *operator new(std::size_t sz, std::align_val_t al, const std::nothrow_t &nt) noexcept (true) + __asm__ (MANGLED_ZNWX_ALIGN_VAL_T_NOTHROW_T); +extern void *operator new[](std::size_t sz, std::align_val_t al, const std::nothrow_t &nt) noexcept (true) + __asm__ (MANGLED_ZNAX_ALIGN_VAL_T_NOTHROW_T); +extern void operator delete(void *p, std::align_val_t al, const std::nothrow_t &nt) noexcept (true) + __asm__ (_SYMSTR (__wrap__ZdlPvSt11align_val_tRKSt9nothrow_t)); +extern void operator delete[](void *p, std::align_val_t al, const std::nothrow_t &nt) noexcept (true) + __asm__ (_SYMSTR (__wrap__ZdaPvSt11align_val_tRKSt9nothrow_t)); extern void * operator new(std::size_t sz) noexcept (false) @@ -66,6 +94,54 @@ operator delete[](void *p) noexcept (true) (*user_data->cxx_malloc->oper_delete__) (p); } +extern void +operator delete(void *p, std::size_t sz) noexcept (true) +{ + (*user_data->cxx_malloc->oper_delete_sz) (p, sz); +} + +extern void +operator delete[](void *p, std::size_t sz) noexcept (true) +{ + (*user_data->cxx_malloc->oper_delete___sz) (p, sz); +} + +extern void * +operator new(std::size_t sz, std::align_val_t al) noexcept (false) +{ + return (*user_data->cxx_malloc->oper_new_al) (sz, al); +} + +extern void * +operator new[](std::size_t sz, std::align_val_t al) noexcept (false) +{ + return (*user_data->cxx_malloc->oper_new___al) (sz, al); +} + +extern void +operator delete(void *p, std::align_val_t al) noexcept (true) +{ + (*user_data->cxx_malloc->oper_delete_al) (p, al); +} + +extern void +operator delete[](void *p, std::align_val_t al) noexcept (true) +{ + (*user_data->cxx_malloc->oper_delete___al) (p, al); +} + +extern void +operator delete(void *p, std::size_t sz, std::align_val_t al) noexcept (true) +{ + (*user_data->cxx_malloc->oper_delete_sz_al) (p, sz, al); +} + +extern void +operator delete[](void *p, std::size_t sz, std::align_val_t al) noexcept (true) +{ + (*user_data->cxx_malloc->oper_delete___sz_al) (p, sz, al); +} + extern void * operator new(std::size_t sz, const std::nothrow_t &nt) noexcept (true) { @@ -89,4 +165,27 @@ operator delete[](void *p, const std::nothrow_t &nt) noexcept (true) { (*user_data->cxx_malloc->oper_delete___nt) (p, nt); } +extern void * +operator new(std::size_t sz, std::align_val_t al, const std::nothrow_t &nt) noexcept (true) +{ + return (*user_data->cxx_malloc->oper_new_al_nt) (sz, al, nt); +} + +extern void * +operator new[](std::size_t sz, std::align_val_t al, const std::nothrow_t &nt) noexcept (true) +{ + return (*user_data->cxx_malloc->oper_new___al_nt) (sz, al, nt); +} + +extern void +operator delete(void *p, std::align_val_t al, const std::nothrow_t &nt) noexcept (true) +{ + (*user_data->cxx_malloc->oper_delete_al_nt) (p, al, nt); +} + +extern void +operator delete[](void *p, std::align_val_t al, const std::nothrow_t &nt) noexcept (true) +{ + (*user_data->cxx_malloc->oper_delete___al_nt) (p, al, nt); +} diff --git a/winsup/cygwin/local_includes/cygwin-cxx.h b/winsup/cygwin/local_includes/cygwin-cxx.h index ccfaa26a0..13db01d0b 100644 --- a/winsup/cygwin/local_includes/cygwin-cxx.h +++ b/winsup/cygwin/local_includes/cygwin-cxx.h @@ -27,6 +27,20 @@ struct per_process_cxx_malloc void *(*oper_new___nt) (std::size_t, const std::nothrow_t &); void (*oper_delete_nt) (void *, const std::nothrow_t &); void (*oper_delete___nt) (void *, const std::nothrow_t &); + /* New in C++14: sized delete */ + void (*oper_delete_sz) (void *, std::size_t); + void (*oper_delete___sz) (void *, std::size_t); + /* New in C++17: aligned new/delete, and combinations with size and nothrow */ + void *(*oper_new_al) (std::size_t, std::align_val_t); + void *(*oper_new___al) (std::size_t, std::align_val_t); + void (*oper_delete_al) (void *, std::align_val_t); + void (*oper_delete___al) (void *, std::align_val_t); + void (*oper_delete_sz_al) (void *, std::size_t, std::align_val_t); + void (*oper_delete___sz_al) (void *, std::size_t, std::align_val_t); + void *(*oper_new_al_nt) (std::size_t, std::align_val_t, const std::nothrow_t &); + void *(*oper_new___al_nt) (std::size_t, std::align_val_t, const std::nothrow_t &); + void (*oper_delete_al_nt) (void *, std::align_val_t, const std::nothrow_t &); + void (*oper_delete___al_nt) (void *, std::align_val_t, const std::nothrow_t &); }; /* Defined in cxx.cc */