With this patch, lib/wine/x86_64-windows/ ends up 100 KB smaller, and I would expect performance benefits too.
From https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-mal...:
Attribute malloc indicates that a function is malloc-like, i.e., that the pointer P returned by the function cannot alias any other pointer valid when the function returns, and moreover no pointers to valid objects occur in any storage addressed by P. In addition, the GCC predicts that a function with the attribute returns non-null in most cases.
Using the attribute with no arguments is designed to improve optimization by relying on the aliasing property it implies. Functions like malloc and calloc have this property because they return a pointer to uninitialized or zeroed-out, newly obtained storage. However, functions like realloc do not have this property, as they may return pointers to storage containing pointers to existing objects. Additionally, since all such functions are assumed to return null only infrequently, callers can be optimized based on that assumption.
From: Brendan Shanks bshanks@codeweavers.com
Signed-off-by: Brendan Shanks bshanks@codeweavers.com --- include/ddk/wdm.h | 12 ++++++------ include/objbase.h | 2 +- include/rpcndr.h | 8 ++++---- include/winbase.h | 6 +++--- include/wincrypt.h | 2 +- include/wine/heap.h | 6 +++--- include/winnt.h | 6 ++++++ include/winternl.h | 2 +- 8 files changed, 25 insertions(+), 19 deletions(-)
diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index b75f452d0da..8517f6dca39 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -1656,10 +1656,10 @@ BOOLEAN WINAPI ExAcquireResourceExclusiveLite(ERESOURCE*,BOOLEAN); BOOLEAN WINAPI ExAcquireResourceSharedLite(ERESOURCE*,BOOLEAN); BOOLEAN WINAPI ExAcquireSharedStarveExclusive(ERESOURCE*,BOOLEAN); BOOLEAN WINAPI ExAcquireSharedWaitForExclusive(ERESOURCE*,BOOLEAN); -PVOID WINAPI ExAllocatePool(POOL_TYPE,SIZE_T) __WINE_ALLOC_SIZE(2); -PVOID WINAPI ExAllocatePoolWithQuota(POOL_TYPE,SIZE_T) __WINE_ALLOC_SIZE(2); -PVOID WINAPI ExAllocatePoolWithTag(POOL_TYPE,SIZE_T,ULONG) __WINE_ALLOC_SIZE(2); -PVOID WINAPI ExAllocatePoolWithQuotaTag(POOL_TYPE,SIZE_T,ULONG) __WINE_ALLOC_SIZE(2); +PVOID WINAPI ExAllocatePool(POOL_TYPE,SIZE_T) __WINE_ALLOC_SIZE(2) __WINE_MALLOC; +PVOID WINAPI ExAllocatePoolWithQuota(POOL_TYPE,SIZE_T) __WINE_ALLOC_SIZE(2) __WINE_MALLOC; +PVOID WINAPI ExAllocatePoolWithTag(POOL_TYPE,SIZE_T,ULONG) __WINE_ALLOC_SIZE(2) __WINE_MALLOC; +PVOID WINAPI ExAllocatePoolWithQuotaTag(POOL_TYPE,SIZE_T,ULONG) __WINE_ALLOC_SIZE(2) __WINE_MALLOC; void WINAPI ExDeleteNPagedLookasideList(PNPAGED_LOOKASIDE_LIST); void WINAPI ExDeletePagedLookasideList(PPAGED_LOOKASIDE_LIST); NTSTATUS WINAPI ExDeleteResourceLite(ERESOURCE*); @@ -1791,8 +1791,8 @@ BOOLEAN WINAPI KeSignalCallDpcSynchronize(void*); NTSTATUS WINAPI KeWaitForMultipleObjects(ULONG,void*[],WAIT_TYPE,KWAIT_REASON,KPROCESSOR_MODE,BOOLEAN,LARGE_INTEGER*,KWAIT_BLOCK*); NTSTATUS WINAPI KeWaitForSingleObject(void*,KWAIT_REASON,KPROCESSOR_MODE,BOOLEAN,LARGE_INTEGER*);
-PVOID WINAPI MmAllocateContiguousMemory(SIZE_T,PHYSICAL_ADDRESS) __WINE_ALLOC_SIZE(1); -PVOID WINAPI MmAllocateNonCachedMemory(SIZE_T) __WINE_ALLOC_SIZE(1); +PVOID WINAPI MmAllocateContiguousMemory(SIZE_T,PHYSICAL_ADDRESS) __WINE_ALLOC_SIZE(1) __WINE_MALLOC; +PVOID WINAPI MmAllocateNonCachedMemory(SIZE_T) __WINE_ALLOC_SIZE(1) __WINE_MALLOC; PMDL WINAPI MmAllocatePagesForMdl(PHYSICAL_ADDRESS,PHYSICAL_ADDRESS,PHYSICAL_ADDRESS,SIZE_T); void WINAPI MmBuildMdlForNonPagedPool(MDL*); NTSTATUS WINAPI MmCopyVirtualMemory(PEPROCESS,void*,PEPROCESS,void*,SIZE_T,KPROCESSOR_MODE,SIZE_T*); diff --git a/include/objbase.h b/include/objbase.h index 11bfc95d989..4b499ffdc0f 100644 --- a/include/objbase.h +++ b/include/objbase.h @@ -317,7 +317,7 @@ HRESULT WINAPI CoGetInstanceFromFile(COSERVERINFO* pServerInfo, CLSID* pClsid, I HRESULT WINAPI CoGetInstanceFromIStorage(COSERVERINFO* pServerInfo, CLSID* pClsid, IUnknown* punkOuter, DWORD dwClsCtx, IStorage* pstg, DWORD dwCount, MULTI_QI* pResults);
HRESULT WINAPI CoGetMalloc(DWORD dwMemContext, LPMALLOC* lpMalloc); -LPVOID WINAPI CoTaskMemAlloc(SIZE_T size) __WINE_ALLOC_SIZE(1); +LPVOID WINAPI CoTaskMemAlloc(SIZE_T size) __WINE_ALLOC_SIZE(1) __WINE_MALLOC; void WINAPI CoTaskMemFree(LPVOID ptr); LPVOID WINAPI CoTaskMemRealloc(LPVOID ptr, SIZE_T size) __WINE_ALLOC_SIZE(2);
diff --git a/include/rpcndr.h b/include/rpcndr.h index 13711f2f2df..b7a5c8c4029 100644 --- a/include/rpcndr.h +++ b/include/rpcndr.h @@ -658,7 +658,7 @@ RPCRTAPI LONG RPC_ENTRY NdrDcomAsyncStubCall( struct IRpcStubBuffer* pThis, struct IRpcChannelBuffer* pChannel, PRPC_MESSAGE pRpcMsg, DWORD * pdwStubPhase );
RPCRTAPI void* RPC_ENTRY - NdrAllocate( PMIDL_STUB_MESSAGE pStubMsg, SIZE_T Len ) __WINE_ALLOC_SIZE(2); + NdrAllocate( PMIDL_STUB_MESSAGE pStubMsg, SIZE_T Len ) __WINE_ALLOC_SIZE(2) __WINE_MALLOC;
RPCRTAPI void RPC_ENTRY NdrClearOutParameters( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, void *ArgAddr ); @@ -668,7 +668,7 @@ RPCRTAPI RPC_STATUS RPC_ENTRY ULONG *pFaultStatus, RPC_STATUS Status_ );
RPCRTAPI void* RPC_ENTRY - NdrOleAllocate( SIZE_T Size ) __WINE_ALLOC_SIZE(1); + NdrOleAllocate( SIZE_T Size ) __WINE_ALLOC_SIZE(1) __WINE_MALLOC; RPCRTAPI void RPC_ENTRY NdrOleFree( void* NodeToFree );
@@ -729,11 +729,11 @@ RPCRTAPI void RPC_ENTRY RPCRTAPI void RPC_ENTRY NdrRpcSmSetClientToOsf( PMIDL_STUB_MESSAGE pMessage ); RPCRTAPI void * RPC_ENTRY - NdrRpcSmClientAllocate( SIZE_T Size ) __WINE_ALLOC_SIZE(1); + NdrRpcSmClientAllocate( SIZE_T Size ) __WINE_ALLOC_SIZE(1) __WINE_MALLOC; RPCRTAPI void RPC_ENTRY NdrRpcSmClientFree( void *NodeToFree ); RPCRTAPI void * RPC_ENTRY - NdrRpcSsDefaultAllocate( SIZE_T Size ) __WINE_ALLOC_SIZE(1); + NdrRpcSsDefaultAllocate( SIZE_T Size ) __WINE_ALLOC_SIZE(1) __WINE_MALLOC; RPCRTAPI void RPC_ENTRY NdrRpcSsDefaultFree( void *NodeToFree );
diff --git a/include/winbase.h b/include/winbase.h index 9fbaa466b54..748a248f56a 100644 --- a/include/winbase.h +++ b/include/winbase.h @@ -2350,7 +2350,7 @@ WINBASEAPI BOOL WINAPI GetXStateFeaturesMask(CONTEXT*,DWORD64*); WINBASEAPI ATOM WINAPI GlobalAddAtomA(LPCSTR); WINBASEAPI ATOM WINAPI GlobalAddAtomW(LPCWSTR); #define GlobalAddAtom WINELIB_NAME_AW(GlobalAddAtom) -WINBASEAPI HGLOBAL WINAPI GlobalAlloc(UINT,SIZE_T) __WINE_ALLOC_SIZE(2); +WINBASEAPI HGLOBAL WINAPI GlobalAlloc(UINT,SIZE_T) __WINE_ALLOC_SIZE(2) __WINE_MALLOC; WINBASEAPI SIZE_T WINAPI GlobalCompact(DWORD); WINBASEAPI ATOM WINAPI GlobalDeleteAtom(ATOM); WINBASEAPI ATOM WINAPI GlobalFindAtomA(LPCSTR); @@ -2373,7 +2373,7 @@ WINBASEAPI BOOL WINAPI GlobalUnlock(HGLOBAL); WINBASEAPI BOOL WINAPI GlobalUnWire(HGLOBAL); WINBASEAPI LPVOID WINAPI GlobalWire(HGLOBAL); #define HasOverlappedIoCompleted(lpOverlapped) ((lpOverlapped)->Internal != STATUS_PENDING) -WINBASEAPI LPVOID WINAPI HeapAlloc(HANDLE,DWORD,SIZE_T) __WINE_ALLOC_SIZE(3); +WINBASEAPI LPVOID WINAPI HeapAlloc(HANDLE,DWORD,SIZE_T) __WINE_ALLOC_SIZE(3) __WINE_MALLOC; WINBASEAPI SIZE_T WINAPI HeapCompact(HANDLE,DWORD); WINBASEAPI HANDLE WINAPI HeapCreate(DWORD,SIZE_T,SIZE_T); WINBASEAPI BOOL WINAPI HeapDestroy(HANDLE); @@ -2440,7 +2440,7 @@ WINBASEAPI HMODULE WINAPI LoadLibraryExW(LPCWSTR,HANDLE,DWORD); WINBASEAPI DWORD WINAPI LoadModule(LPCSTR,LPVOID); WINBASEAPI HMODULE WINAPI LoadPackagedLibrary(LPCWSTR,DWORD); WINBASEAPI HGLOBAL WINAPI LoadResource(HMODULE,HRSRC); -WINBASEAPI HLOCAL WINAPI LocalAlloc(UINT,SIZE_T) __WINE_ALLOC_SIZE(2); +WINBASEAPI HLOCAL WINAPI LocalAlloc(UINT,SIZE_T) __WINE_ALLOC_SIZE(2) __WINE_MALLOC; WINBASEAPI SIZE_T WINAPI LocalCompact(UINT); WINBASEAPI UINT WINAPI LocalFlags(HLOCAL); WINBASEAPI HLOCAL WINAPI LocalFree(HLOCAL); diff --git a/include/wincrypt.h b/include/wincrypt.h index 77b2fb5d7cf..8adbd2c1300 100644 --- a/include/wincrypt.h +++ b/include/wincrypt.h @@ -4043,7 +4043,7 @@ WINADVAPI BOOL WINAPI CryptVerifySignatureW (HCRYPTHASH, const BYTE *, DWORD, HC #define CryptVerifySignature WINELIB_NAME_AW(CryptVerifySignature)
/* crypt32.dll functions */ -LPVOID WINAPI CryptMemAlloc(ULONG cbSize) __WINE_ALLOC_SIZE(1); +LPVOID WINAPI CryptMemAlloc(ULONG cbSize) __WINE_ALLOC_SIZE(1) __WINE_MALLOC; LPVOID WINAPI CryptMemRealloc(LPVOID pv, ULONG cbSize) __WINE_ALLOC_SIZE(2); VOID WINAPI CryptMemFree(LPVOID pv);
diff --git a/include/wine/heap.h b/include/wine/heap.h index fb687c92393..f88942bbb00 100644 --- a/include/wine/heap.h +++ b/include/wine/heap.h @@ -24,12 +24,12 @@
#include <winbase.h>
-static inline void * __WINE_ALLOC_SIZE(1) heap_alloc(SIZE_T len) +static inline void * __WINE_ALLOC_SIZE(1) __WINE_MALLOC heap_alloc(SIZE_T len) { return HeapAlloc(GetProcessHeap(), 0, len); }
-static inline void * __WINE_ALLOC_SIZE(1) heap_alloc_zero(SIZE_T len) +static inline void * __WINE_ALLOC_SIZE(1) __WINE_MALLOC heap_alloc_zero(SIZE_T len) { return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); } @@ -46,7 +46,7 @@ static inline void heap_free(void *mem) HeapFree(GetProcessHeap(), 0, mem); }
-static inline void * __WINE_ALLOC_SIZE(1,2) heap_calloc(SIZE_T count, SIZE_T size) +static inline void * __WINE_ALLOC_SIZE(1,2) __WINE_MALLOC heap_calloc(SIZE_T count, SIZE_T size) { SIZE_T len = count * size;
diff --git a/include/winnt.h b/include/winnt.h index 79df4259f59..a0b430b47d6 100644 --- a/include/winnt.h +++ b/include/winnt.h @@ -204,6 +204,12 @@ extern "C" { #define __WINE_ALLOC_SIZE(...) #endif
+#if defined(__GNUC__) && (__GNUC__ > 2) +#define __WINE_MALLOC __attribute__((malloc)) +#else +#define __WINE_MALLOC +#endif + /* Anonymous union/struct handling */
#ifndef NONAMELESSSTRUCT diff --git a/include/winternl.h b/include/winternl.h index a4cbcb316cb..43a4ddf2f39 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -4200,7 +4200,7 @@ NTSYSAPI PVOID WINAPI RtlAddVectoredExceptionHandler(ULONG,PVECTORED_EXCEPTI NTSYSAPI NTSTATUS WINAPI RtlAdjustPrivilege(ULONG,BOOLEAN,BOOLEAN,PBOOLEAN); NTSYSAPI NTSTATUS WINAPI RtlAllocateAndInitializeSid(PSID_IDENTIFIER_AUTHORITY,BYTE,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,PSID *); NTSYSAPI RTL_HANDLE * WINAPI RtlAllocateHandle(RTL_HANDLE_TABLE *,ULONG *); -NTSYSAPI PVOID WINAPI RtlAllocateHeap(HANDLE,ULONG,SIZE_T) __WINE_ALLOC_SIZE(3); +NTSYSAPI PVOID WINAPI RtlAllocateHeap(HANDLE,ULONG,SIZE_T) __WINE_ALLOC_SIZE(3) __WINE_MALLOC; NTSYSAPI WCHAR WINAPI RtlAnsiCharToUnicodeChar(LPSTR *); NTSYSAPI DWORD WINAPI RtlAnsiStringToUnicodeSize(const STRING *); NTSYSAPI NTSTATUS WINAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING,PCANSI_STRING,BOOLEAN);
Shouldn't this specify the deallocator too while we're at it changing global headers? It could perhaps find mismatches, or perhaps optimize even more combined malloc / free?
Le 14/05/2022 à 10:50, Rémi Bernon (@rbernon) a écrit :
Shouldn't this specify the deallocator too while we're at it changing global headers? It could perhaps find mismatches, or perhaps optimize even more combined malloc / free?
yes it could (even if the gcc version supporting it is newer)
could also be done for msvcrt fopen/fclose
from the initial patch, I wonder if adding the attribute to inline functions in heap.h is needed (as called function are already marked)
I've been using this patch (generates one potential mismatch to be fixed)
A+
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=114707
Your paranoid android.
=== debian11 (build log) ===
error: patch failed: include/winnt.h:203 Task: Patch failed to apply
=== debian11 (build log) ===
error: patch failed: include/winnt.h:203 Task: Patch failed to apply
On Sat May 14 12:30:10 2022 +0000, **** wrote:
Eric Pouech replied on the mailing list:
Le 14/05/2022 à 10:50, Rémi Bernon (@rbernon) a écrit : > Shouldn't this specify the deallocator too while we're at it changing global headers? It could perhaps find mismatches, or perhaps optimize even more combined malloc / free? > yes it could (even if the gcc version supporting it is newer) could also be done for msvcrt fopen/fclose from the initial patch, I wonder if adding the attribute to inline functions in heap.h is needed (as called function are already marked) I've been using this patch (generates one potential mismatch to be fixed) A+ diff --git a/include/winbase.h b/include/winbase.h index 0a0bfde9d10..879f412186a 100644 --- a/include/winbase.h +++ b/include/winbase.h @@ -2349,7 +2349,8 @@ WINBASEAPI BOOL WINAPI GetXStateFeaturesMask(CONTEXT*,DWORD64*); WINBASEAPI ATOM WINAPI GlobalAddAtomA(LPCSTR); WINBASEAPI ATOM WINAPI GlobalAddAtomW(LPCWSTR); #define GlobalAddAtom WINELIB_NAME_AW(GlobalAddAtom) -WINBASEAPI HGLOBAL WINAPI GlobalAlloc(UINT,SIZE_T) __WINE_ALLOC_SIZE(2); +WINBASEAPI HGLOBAL WINAPI GlobalFree(HGLOBAL); +WINBASEAPI HGLOBAL WINAPI GlobalAlloc(UINT,SIZE_T) __WINE_ALLOC_SIZE(2) __WINE_MALLOC(GlobalFree, 1); WINBASEAPI SIZE_T WINAPI GlobalCompact(DWORD); WINBASEAPI ATOM WINAPI GlobalDeleteAtom(ATOM); WINBASEAPI ATOM WINAPI GlobalFindAtomA(LPCSTR); @@ -2357,7 +2358,6 @@ WINBASEAPI ATOM WINAPI GlobalFindAtomW(LPCWSTR); #define GlobalFindAtom WINELIB_NAME_AW(GlobalFindAtom) WINBASEAPI VOID WINAPI GlobalFix(HGLOBAL); WINBASEAPI UINT WINAPI GlobalFlags(HGLOBAL); -WINBASEAPI HGLOBAL WINAPI GlobalFree(HGLOBAL); WINBASEAPI UINT WINAPI GlobalGetAtomNameA(ATOM,LPSTR,INT); WINBASEAPI UINT WINAPI GlobalGetAtomNameW(ATOM,LPWSTR,INT); #define GlobalGetAtomName WINELIB_NAME_AW(GlobalGetAtomName) @@ -2365,20 +2365,20 @@ WINBASEAPI HGLOBAL WINAPI GlobalHandle(LPCVOID); WINBASEAPI LPVOID WINAPI GlobalLock(HGLOBAL); WINBASEAPI VOID WINAPI GlobalMemoryStatus(LPMEMORYSTATUS); WINBASEAPI BOOL WINAPI GlobalMemoryStatusEx(LPMEMORYSTATUSEX); -WINBASEAPI HGLOBAL WINAPI GlobalReAlloc(HGLOBAL,SIZE_T,UINT) __WINE_ALLOC_SIZE(2); +WINBASEAPI HGLOBAL WINAPI GlobalReAlloc(HGLOBAL,SIZE_T,UINT) __WINE_ALLOC_SIZE(2) __WINE_REALLOC(GlobalFree, 1); WINBASEAPI SIZE_T WINAPI GlobalSize(HGLOBAL); WINBASEAPI VOID WINAPI GlobalUnfix(HGLOBAL); WINBASEAPI BOOL WINAPI GlobalUnlock(HGLOBAL); WINBASEAPI BOOL WINAPI GlobalUnWire(HGLOBAL); WINBASEAPI LPVOID WINAPI GlobalWire(HGLOBAL); #define HasOverlappedIoCompleted(lpOverlapped) ((lpOverlapped)->Internal != STATUS_PENDING) -WINBASEAPI LPVOID WINAPI HeapAlloc(HANDLE,DWORD,SIZE_T) __WINE_ALLOC_SIZE(3); +WINBASEAPI BOOL WINAPI HeapFree(HANDLE,DWORD,LPVOID); +WINBASEAPI LPVOID WINAPI HeapAlloc(HANDLE,DWORD,SIZE_T) __WINE_ALLOC_SIZE(3) __WINE_MALLOC(HeapFree, 3); WINBASEAPI SIZE_T WINAPI HeapCompact(HANDLE,DWORD); WINBASEAPI HANDLE WINAPI HeapCreate(DWORD,SIZE_T,SIZE_T); WINBASEAPI BOOL WINAPI HeapDestroy(HANDLE); -WINBASEAPI BOOL WINAPI HeapFree(HANDLE,DWORD,LPVOID); WINBASEAPI BOOL WINAPI HeapLock(HANDLE); -WINBASEAPI LPVOID WINAPI HeapReAlloc(HANDLE,DWORD,LPVOID,SIZE_T) __WINE_ALLOC_SIZE(4); +WINBASEAPI LPVOID WINAPI HeapReAlloc(HANDLE,DWORD,LPVOID,SIZE_T) __WINE_ALLOC_SIZE(4) __WINE_REALLOC(HeapFree, 3); WINBASEAPI BOOL WINAPI HeapQueryInformation(HANDLE,HEAP_INFORMATION_CLASS,PVOID,SIZE_T,PSIZE_T); WINBASEAPI BOOL WINAPI HeapSetInformation(HANDLE,HEAP_INFORMATION_CLASS,PVOID,SIZE_T); WINBASEAPI SIZE_T WINAPI HeapSize(HANDLE,DWORD,LPCVOID); @@ -2438,13 +2438,13 @@ WINBASEAPI HMODULE WINAPI LoadLibraryExW(LPCWSTR,HANDLE,DWORD); WINBASEAPI DWORD WINAPI LoadModule(LPCSTR,LPVOID); WINBASEAPI HMODULE WINAPI LoadPackagedLibrary(LPCWSTR,DWORD); WINBASEAPI HGLOBAL WINAPI LoadResource(HMODULE,HRSRC); -WINBASEAPI HLOCAL WINAPI LocalAlloc(UINT,SIZE_T) __WINE_ALLOC_SIZE(2); +WINBASEAPI HLOCAL WINAPI LocalFree(HLOCAL); +WINBASEAPI HLOCAL WINAPI LocalAlloc(UINT,SIZE_T) __WINE_ALLOC_SIZE(2) __WINE_MALLOC(LocalFree, 1); WINBASEAPI SIZE_T WINAPI LocalCompact(UINT); WINBASEAPI UINT WINAPI LocalFlags(HLOCAL); -WINBASEAPI HLOCAL WINAPI LocalFree(HLOCAL); WINBASEAPI HLOCAL WINAPI LocalHandle(LPCVOID); WINBASEAPI LPVOID WINAPI LocalLock(HLOCAL); -WINBASEAPI HLOCAL WINAPI LocalReAlloc(HLOCAL,SIZE_T,UINT) __WINE_ALLOC_SIZE(2); +WINBASEAPI HLOCAL WINAPI LocalReAlloc(HLOCAL,SIZE_T,UINT) __WINE_ALLOC_SIZE(2) __WINE_REALLOC(LocalFree, 1); WINBASEAPI SIZE_T WINAPI LocalShrink(HGLOBAL,UINT); WINBASEAPI SIZE_T WINAPI LocalSize(HLOCAL); WINBASEAPI BOOL WINAPI LocalUnlock(HLOCAL); diff --git a/include/winnt.h b/include/winnt.h index c80efee077d..ff9b55b7ea2 100644 --- a/include/winnt.h +++ b/include/winnt.h @@ -203,6 +203,13 @@ extern "C" { #else #define __WINE_ALLOC_SIZE(x) #endif +#if defined(__GNUC__) && ((__GNUC__ > 11) || ((__GNUC__ == 11) && (__GNUC_MINOR__ >= 2))) +#define __WINE_MALLOC(x, y) __attribute__((malloc, malloc(x, y))) +#define __WINE_REALLOC(x, y) __attribute__((malloc(x, y))) +#else +#define __WINE_MALLOC(x, y) +#define __WINE_REALLOC(x, y) +#endif /* Anonymous union/struct handling */
I guess I'll also point out FWIW that the MSVC equivalent to `__attribute__((malloc))` (no arguments) is `__declspec(restrict)`. It's available since MSVC 2005 (MSC 14.0). (Not to be confused with `__declspec(noalias)`, which is actually a weaker form of GCC's `__attribute__((pure))`.)
Also, am I the only one disturbed by the fact that the GCC developers chose to reuse an attribute name and give it **totally different semantics** when it has arguments vs. when it doesn't?
I was planning to do it separately, but yep I can add the deallocator to this series.
I was going to use a separate define (something like __WINE_DEALLOC), since as mentioned it could also be useful for non-malloc functions like fopen/fclose, SysAllocString/SysFreeString, etc.
And agreed, I don’t know what they were thinking by overloading the long-preexisting malloc attribute for this. If nothing else, it prevents the use of __has_attribute to detect the deallocator version, and checking the GNUC version must be done instead.
On 5/15/22 23:27, Brendan Shanks (@bshanks) wrote:
I was going to use a separate define (something like __WINE_DEALLOC), since as mentioned it could also be useful for non-malloc functions like fopen/fclose, SysAllocString/SysFreeString, etc.
Is SysAllocString not malloc-like? It has a header, but I assume that shouldn't matter...