try to unify ownership over gcc and clang

This commit is contained in:
leitner
2025-03-20 10:57:15 +00:00
parent 404bc78a11
commit 246ea3f94d
3 changed files with 36 additions and 23 deletions

View File

@@ -35,25 +35,25 @@ typedef struct buffer {
/* Initialize a buffer with an existing memory area, which the buffer
* will NOT take ownership of (i.e. won't free the memory when it's done) */
__bufout(4,5)
att_holds(4)
att_holds(malloc,4)
void buffer_init(buffer* b, ssize_t (*op)(), int fd, char* y, size_t ylen);
/* Initialize a buffer with an existing memory area, which the buffer
* WILL take ownership of (it will call free() on it when it's done) */
__bufout(4,5)
att_free(4)
att_free(malloc,4)
void buffer_init_free(buffer* b,ssize_t (*op)(),int fd,char* y,size_t ylen);
/* Call buffer_init with op=read(), return 0.
* If fd==-1, return -1 instead, leaving b untouched. */
__bufout(3,4)
att_holds(3)
att_holds(malloc,3)
int buffer_init_read(buffer* b, int fd, char* y, size_t ylen);
/* Call buffer_init with op=write(), return 0.
* If fd==-1, return -1 instead, leaving b untouched. */
__bufout(3,4)
att_holds(3)
att_holds(malloc,3)
int buffer_init_write(buffer* b, int fd, char* y, size_t ylen);
/* Will allocate a buffer of size ylen and then call
@@ -77,19 +77,19 @@ int buffer_init_write_allocbuf(buffer* b, int fd, size_t ylen);
* actually attempt to read from any actual file.
* Does not take ownership. Useful for testing. */
__bufin(2,3)
att_holds(2)
att_holds(malloc,2)
void buffer_init_staticcontents(buffer* b,char* y,size_t ylen);
/* Same but the buffer takes ownership of the static buffer and frees it
* in buffer_close. */
__bufin(2,3)
att_free(2)
att_free(malloc,2)
void buffer_init_staticcontents_free(buffer* b,char* y,size_t ylen);
/* Set buffer->deinit to this if you want buffer_close() to call free() on
* the associated memory buffer */
att_free(1)
att_free(malloc,1)
void buffer_free(void* buf);
/* Set buffer->deinit to this if you want buffer_close() to call munmap() on

View File

@@ -99,8 +99,8 @@
#define att_alloc(x) __attribute__((alloc_size(x)))
#define att_calloc(x,y) __attribute__((alloc_size(x,y)))
#else
#define att_alloc
#define att_calloc
#define att_alloc(x)
#define att_calloc(x,y)
#endif
// Function attributes.
@@ -146,7 +146,7 @@
// abort compilation on error.
#if GCC_VERSION_ATLEAST(4, 3)
#define att_warn(message) __attribute__((__warning__(message)))
#define att_error(message) __attribute__((__warning__(message)))
#define att_error(message) __attribute__((__error__(message)))
#else
#define att_warn(message)
#define att_error(message)
@@ -215,14 +215,28 @@
#endif // !defined(__GNUC__)
#endif // !defined(__dietlibc__
// in order to cover both clang and gcc, we'll need a convention
// att_new(myfree,1) void* mymalloc(size_t n);
// here myfree is the name of the free function, and 1 means you pass
// the pointer you want to free as first argument to myfree.
// att_free(myfree,1) void myfree(void* freeme);
// same meaning of id and idx here
// att_holds(myfree,2) int add_to_list_and_give_ownership(list* l,void* ptr);
// myfree is the name of the free function so that clang can link them
// and 2 is the index of the pointer whose ownership is transferred
// use "malloc" as id to indicate regular malloc'ed pointers
#if __has_attribute(ownership_takes)
#define att_new __attribute__((ownership_returns(malloc)))
#define att_free(idx) __attribute__((ownership_takes(malloc, idx)))
#define att_holds(idx) __attribute__((ownership_holds(malloc, idx)))
#define att_new(id,idx) __attribute__((ownership_returns(id)))
#define att_free(id,idx) __attribute__((ownership_takes(id, idx)))
#define att_holds(id,idx) __attribute__((ownership_holds(id, idx)))
#elif __GNUC__ >= 11
#define att_new(id,idx) __attribute__((malloc(id,idx)))
#define att_free(id,idx)
#define att_holds(id,idx)
#else
#define att_new
#define att_free(idx)
#define att_holds(idx)
#define att_new(id,idx)
#define att_free(id,idx)
#define att_holds(id,idx)
#endif
#if __GNUC__ >= 11

13
iob.h
View File

@@ -59,24 +59,23 @@ att_warn_unused_result
int iob_init_autofree(io_batch* b,size_t hint_entries);
/* malloc and initialize an io_batch */
att_free_with(iob_free,1)
att_new
att_new(iob_free,1)
io_batch* iob_new(size_t hint_entries);
/* malloc and initialize an io_batch that auto-frees entries as soon as
* iob_send/iob_write have written them */
att_free_with(iob_free,1)
att_new(iob_free,1)
io_batch* iob_new_autofree(size_t hint_entries);
/* queue buffer in io_batch */
att_readn(2,3)
att_holds(1)
att_holds(malloc,2)
int iob_addbuf(io_batch* b,const void* buf,uint64 n);
/* queue buffer in io_batch, and give ownership to batch. */
/* the io_batch functions will take care of freeing it. */
att_readn(2,3)
att_free(1)
att_free(malloc,2)
int iob_addbuf_free(io_batch* b,const void* buf,uint64 n);
/* queue mmapped memory reagion in io_batch, and give ownership to batch. */
@@ -86,13 +85,13 @@ int iob_addbuf_munmap(io_batch* b,const void* buf,uint64 n);
/* queue asciiz string in io_batch. */
att_read(2)
att_holds(2)
att_holds(malloc,2)
int iob_adds(io_batch* b,const char* s);
/* queue asciiz string in io_batch, and give ownership to batch. */
/* the io_batch functions will take care of freeing it. */
att_read(2)
att_free(2)
att_free(malloc,2)
int iob_adds_free(io_batch* b,const char* s);
/* queue file contents in io_batch. */