The GCC documentation [1] says that the attribute 'malloc (deallocator, 1)' does not work on inline functions. IMO, this restriction is not tenable in the long run (because the semantics of a function don't depend on whether it is inline or not, and because in C++ the majority of all functions is inline).
So, let me add the attributes in a couple of more modules, but commented out until the day GCC lifts this limitation. [1] https://gcc.gnu.org/onlinedocs/gcc-11.2.0/gcc/Common-Function-Attributes.html 2021-08-07 Bruno Haible <[email protected]> list, set, oset, map, omap: Prepare allocation-deallocation checking. * lib/gl_list.h (gl_list_create_empty, gl_list_nx_create_empty, gl_list_create, gl_list_nx_create): Add comment that deallocation must happen through 'gl_list_free'. * lib/gl_xlist.h (gl_list_create_empty, gl_list_create): Likewise. * lib/gl_sublist.h (gl_sublist_create, gl_sublist_nx_create): Likewise. * lib/gl_xsublist.h (gl_sublist_create): Likewise. * lib/gl_set.h (gl_set_create_empty, gl_set_nx_create_empty): Add comment that deallocation must happen through 'gl_set_free'. * lib/gl_xset.h (gl_set_create_empty): Likewise. * lib/gl_oset.h (gl_oset_create_empty, gl_oset_nx_create_empty): Add comment that deallocation must happen through 'gl_oset_free'. * lib/gl_xoset.h (gl_oset_create_empty): Likewise. * lib/gl_map.h (gl_map_create_empty, gl_map_nx_create_empty): Add comment that deallocation must happen through 'gl_map_free'. * lib/gl_xmap.h (gl_map_create_empty): Likewise. * lib/gl_omap.h (gl_omap_create_empty, gl_omap_nx_create_empty): Add comment that deallocation must happen through 'gl_omap_free'. * lib/gl_xomap.h (gl_omap_create_empty): Likewise. diff --git a/lib/gl_list.h b/lib/gl_list.h index e2da4f1..3374ae2 100644 --- a/lib/gl_list.h +++ b/lib/gl_list.h @@ -152,13 +152,16 @@ extern gl_list_t gl_list_create_empty (gl_list_implementation_t implementation, gl_listelement_equals_fn equals_fn, gl_listelement_hashcode_fn hashcode_fn, gl_listelement_dispose_fn dispose_fn, - bool allow_duplicates); + bool allow_duplicates) + /*_GL_ATTRIBUTE_DEALLOC (gl_list_free, 1)*/ + _GL_ATTRIBUTE_RETURNS_NONNULL; /* Likewise. Returns NULL upon out-of-memory. */ extern gl_list_t gl_list_nx_create_empty (gl_list_implementation_t implementation, gl_listelement_equals_fn equals_fn, gl_listelement_hashcode_fn hashcode_fn, gl_listelement_dispose_fn dispose_fn, - bool allow_duplicates); + bool allow_duplicates) + /*_GL_ATTRIBUTE_DEALLOC (gl_list_free, 1)*/; /* Creates a list with given contents. IMPLEMENTATION is one of GL_ARRAY_LIST, GL_CARRAY_LIST, GL_LINKED_LIST, @@ -177,14 +180,17 @@ extern gl_list_t gl_list_create (gl_list_implementation_t implementation, gl_listelement_hashcode_fn hashcode_fn, gl_listelement_dispose_fn dispose_fn, bool allow_duplicates, - size_t count, const void **contents); + size_t count, const void **contents) + /*_GL_ATTRIBUTE_DEALLOC (gl_list_free, 1)*/ + _GL_ATTRIBUTE_RETURNS_NONNULL; /* Likewise. Returns NULL upon out-of-memory. */ extern gl_list_t gl_list_nx_create (gl_list_implementation_t implementation, gl_listelement_equals_fn equals_fn, gl_listelement_hashcode_fn hashcode_fn, gl_listelement_dispose_fn dispose_fn, bool allow_duplicates, - size_t count, const void **contents); + size_t count, const void **contents) + /*_GL_ATTRIBUTE_DEALLOC (gl_list_free, 1)*/; /* Returns the current number of elements in a list. */ extern size_t gl_list_size (gl_list_t list); @@ -591,7 +597,9 @@ struct gl_list_impl_base /* Define all functions of this file as accesses to the struct gl_list_implementation. */ -GL_LIST_INLINE gl_list_t +GL_LIST_INLINE +/*_GL_ATTRIBUTE_DEALLOC (gl_list_free, 1)*/ +gl_list_t gl_list_nx_create_empty (gl_list_implementation_t implementation, gl_listelement_equals_fn equals_fn, gl_listelement_hashcode_fn hashcode_fn, @@ -603,7 +611,9 @@ gl_list_nx_create_empty (gl_list_implementation_t implementation, allow_duplicates); } -GL_LIST_INLINE gl_list_t +GL_LIST_INLINE +/*_GL_ATTRIBUTE_DEALLOC (gl_list_free, 1)*/ +gl_list_t gl_list_nx_create (gl_list_implementation_t implementation, gl_listelement_equals_fn equals_fn, gl_listelement_hashcode_fn hashcode_fn, diff --git a/lib/gl_map.h b/lib/gl_map.h index 118d4e3..a0c9f93 100644 --- a/lib/gl_map.h +++ b/lib/gl_map.h @@ -117,13 +117,16 @@ extern gl_map_t gl_map_create_empty (gl_map_implementation_t implementation, gl_mapkey_equals_fn equals_fn, gl_mapkey_hashcode_fn hashcode_fn, gl_mapkey_dispose_fn kdispose_fn, - gl_mapvalue_dispose_fn vdispose_fn); + gl_mapvalue_dispose_fn vdispose_fn) + /*_GL_ATTRIBUTE_DEALLOC (gl_map_free, 1)*/ + _GL_ATTRIBUTE_RETURNS_NONNULL; /* Likewise. Returns NULL upon out-of-memory. */ extern gl_map_t gl_map_nx_create_empty (gl_map_implementation_t implementation, gl_mapkey_equals_fn equals_fn, gl_mapkey_hashcode_fn hashcode_fn, gl_mapkey_dispose_fn kdispose_fn, - gl_mapvalue_dispose_fn vdispose_fn); + gl_mapvalue_dispose_fn vdispose_fn) + /*_GL_ATTRIBUTE_DEALLOC (gl_map_free, 1)*/; /* Returns the current number of pairs in a map. */ extern size_t gl_map_size (gl_map_t map); @@ -255,7 +258,9 @@ struct gl_map_impl_base /* Define most functions of this file as accesses to the struct gl_map_implementation. */ -GL_MAP_INLINE gl_map_t +GL_MAP_INLINE +/*_GL_ATTRIBUTE_DEALLOC (gl_map_free, 1)*/ +gl_map_t gl_map_nx_create_empty (gl_map_implementation_t implementation, gl_mapkey_equals_fn equals_fn, gl_mapkey_hashcode_fn hashcode_fn, diff --git a/lib/gl_omap.h b/lib/gl_omap.h index b2dacfb..f187d5d 100644 --- a/lib/gl_omap.h +++ b/lib/gl_omap.h @@ -117,12 +117,15 @@ typedef const struct gl_omap_implementation * gl_omap_implementation_t; extern gl_omap_t gl_omap_create_empty (gl_omap_implementation_t implementation, gl_mapkey_compar_fn compar_fn, gl_mapkey_dispose_fn kdispose_fn, - gl_mapvalue_dispose_fn vdispose_fn); + gl_mapvalue_dispose_fn vdispose_fn) + /*_GL_ATTRIBUTE_DEALLOC (gl_omap_free, 1)*/ + _GL_ATTRIBUTE_RETURNS_NONNULL; /* Likewise. Returns NULL upon out-of-memory. */ extern gl_omap_t gl_omap_nx_create_empty (gl_omap_implementation_t implementation, gl_mapkey_compar_fn compar_fn, gl_mapkey_dispose_fn kdispose_fn, - gl_mapvalue_dispose_fn vdispose_fn); + gl_mapvalue_dispose_fn vdispose_fn) + /*_GL_ATTRIBUTE_DEALLOC (gl_omap_free, 1)*/; /* Returns the current number of pairs in an ordered map. */ extern size_t gl_omap_size (gl_omap_t map); @@ -265,7 +268,9 @@ struct gl_omap_impl_base /* Define most functions of this file as accesses to the struct gl_omap_implementation. */ -GL_OMAP_INLINE gl_omap_t +GL_OMAP_INLINE +/*_GL_ATTRIBUTE_DEALLOC (gl_omap_free, 1)*/ +gl_omap_t gl_omap_nx_create_empty (gl_omap_implementation_t implementation, gl_mapkey_compar_fn compar_fn, gl_mapkey_dispose_fn kdispose_fn, diff --git a/lib/gl_oset.h b/lib/gl_oset.h index ac90f04..44e7ef3 100644 --- a/lib/gl_oset.h +++ b/lib/gl_oset.h @@ -107,11 +107,14 @@ typedef const struct gl_oset_implementation * gl_oset_implementation_t; /* declared in gl_xoset.h */ extern gl_oset_t gl_oset_create_empty (gl_oset_implementation_t implementation, gl_setelement_compar_fn compar_fn, - gl_setelement_dispose_fn dispose_fn); + gl_setelement_dispose_fn dispose_fn) + /*_GL_ATTRIBUTE_DEALLOC (gl_oset_free, 1)*/ + _GL_ATTRIBUTE_RETURNS_NONNULL; /* Likewise. Returns NULL upon out-of-memory. */ extern gl_oset_t gl_oset_nx_create_empty (gl_oset_implementation_t implementation, gl_setelement_compar_fn compar_fn, - gl_setelement_dispose_fn dispose_fn); + gl_setelement_dispose_fn dispose_fn) + /*_GL_ATTRIBUTE_DEALLOC (gl_oset_free, 1)*/; /* Returns the current number of elements in an ordered set. */ extern size_t gl_oset_size (gl_oset_t set); @@ -243,7 +246,9 @@ struct gl_oset_impl_base /* Define all functions of this file as accesses to the struct gl_oset_implementation. */ -GL_OSET_INLINE gl_oset_t +GL_OSET_INLINE +/*_GL_ATTRIBUTE_DEALLOC (gl_oset_free, 1)*/ +gl_oset_t gl_oset_nx_create_empty (gl_oset_implementation_t implementation, gl_setelement_compar_fn compar_fn, gl_setelement_dispose_fn dispose_fn) diff --git a/lib/gl_set.h b/lib/gl_set.h index 4e68cc7..aa803e6 100644 --- a/lib/gl_set.h +++ b/lib/gl_set.h @@ -106,12 +106,15 @@ typedef const struct gl_set_implementation * gl_set_implementation_t; extern gl_set_t gl_set_create_empty (gl_set_implementation_t implementation, gl_setelement_equals_fn equals_fn, gl_setelement_hashcode_fn hashcode_fn, - gl_setelement_dispose_fn dispose_fn); + gl_setelement_dispose_fn dispose_fn) + /*_GL_ATTRIBUTE_DEALLOC (gl_set_free, 1)*/ + _GL_ATTRIBUTE_RETURNS_NONNULL; /* Likewise. Returns NULL upon out-of-memory. */ extern gl_set_t gl_set_nx_create_empty (gl_set_implementation_t implementation, gl_setelement_equals_fn equals_fn, gl_setelement_hashcode_fn hashcode_fn, - gl_setelement_dispose_fn dispose_fn); + gl_setelement_dispose_fn dispose_fn) + /*_GL_ATTRIBUTE_DEALLOC (gl_set_free, 1)*/; /* Returns the current number of elements in a set. */ extern size_t gl_set_size (gl_set_t set); @@ -209,7 +212,9 @@ struct gl_set_impl_base /* Define all functions of this file as accesses to the struct gl_set_implementation. */ -GL_SET_INLINE gl_set_t +GL_SET_INLINE +/*_GL_ATTRIBUTE_DEALLOC (gl_set_free, 1)*/ +gl_set_t gl_set_nx_create_empty (gl_set_implementation_t implementation, gl_setelement_equals_fn equals_fn, gl_setelement_hashcode_fn hashcode_fn, diff --git a/lib/gl_sublist.h b/lib/gl_sublist.h index eb6fb73..f1bf68d 100644 --- a/lib/gl_sublist.h +++ b/lib/gl_sublist.h @@ -35,11 +35,14 @@ extern "C" { */ #if 0 /* declared in gl_xsublist.h */ extern gl_list_t gl_sublist_create (gl_list_t whole_list, - size_t start_index, size_t end_index); + size_t start_index, size_t end_index) + /*_GL_ATTRIBUTE_DEALLOC (gl_list_free, 1)*/ + _GL_ATTRIBUTE_RETURNS_NONNULL; #endif /* Likewise. Returns NULL upon out-of-memory. */ extern gl_list_t gl_sublist_nx_create (gl_list_t whole_list, - size_t start_index, size_t end_index); + size_t start_index, size_t end_index) + /*_GL_ATTRIBUTE_DEALLOC (gl_list_free, 1)*/; #ifdef __cplusplus diff --git a/lib/gl_xlist.h b/lib/gl_xlist.h index 87fd6ea..7e66ab2 100644 --- a/lib/gl_xlist.h +++ b/lib/gl_xlist.h @@ -41,13 +41,17 @@ extern gl_list_t gl_list_create_empty (gl_list_implementation_t implementation, gl_listelement_equals_fn equals_fn, gl_listelement_hashcode_fn hashcode_fn, gl_listelement_dispose_fn dispose_fn, - bool allow_duplicates); + bool allow_duplicates) + /*_GL_ATTRIBUTE_DEALLOC (gl_list_free, 1)*/ + _GL_ATTRIBUTE_RETURNS_NONNULL; extern gl_list_t gl_list_create (gl_list_implementation_t implementation, gl_listelement_equals_fn equals_fn, gl_listelement_hashcode_fn hashcode_fn, gl_listelement_dispose_fn dispose_fn, bool allow_duplicates, - size_t count, const void **contents); + size_t count, const void **contents) + /*_GL_ATTRIBUTE_DEALLOC (gl_list_free, 1)*/ + _GL_ATTRIBUTE_RETURNS_NONNULL; extern void gl_list_node_set_value (gl_list_t list, gl_list_node_t node, const void *elt); extern gl_list_node_t gl_list_set_at (gl_list_t list, size_t position, @@ -67,7 +71,10 @@ extern gl_list_node_t gl_sortedlist_add (gl_list_t list, const void *elt); #endif -GL_XLIST_INLINE gl_list_t +GL_XLIST_INLINE +/*_GL_ATTRIBUTE_DEALLOC (gl_list_free, 1)*/ +_GL_ATTRIBUTE_RETURNS_NONNULL +gl_list_t gl_list_create_empty (gl_list_implementation_t implementation, gl_listelement_equals_fn equals_fn, gl_listelement_hashcode_fn hashcode_fn, @@ -82,7 +89,10 @@ gl_list_create_empty (gl_list_implementation_t implementation, return result; } -GL_XLIST_INLINE gl_list_t +GL_XLIST_INLINE +/*_GL_ATTRIBUTE_DEALLOC (gl_list_free, 1)*/ +_GL_ATTRIBUTE_RETURNS_NONNULL +gl_list_t gl_list_create (gl_list_implementation_t implementation, gl_listelement_equals_fn equals_fn, gl_listelement_hashcode_fn hashcode_fn, diff --git a/lib/gl_xmap.h b/lib/gl_xmap.h index 1edf44b..01bb9de 100644 --- a/lib/gl_xmap.h +++ b/lib/gl_xmap.h @@ -42,13 +42,18 @@ extern gl_map_t gl_map_create_empty (gl_map_implementation_t implementation, gl_mapkey_equals_fn equals_fn, gl_mapkey_hashcode_fn hashcode_fn, gl_mapkey_dispose_fn kdispose_fn, - gl_mapvalue_dispose_fn vdispose_fn); + gl_mapvalue_dispose_fn vdispose_fn) + /*_GL_ATTRIBUTE_DEALLOC (gl_map_free, 1)*/ + _GL_ATTRIBUTE_RETURNS_NONNULL; extern bool gl_map_put (gl_map_t map, const void *key, const void *value); extern bool gl_map_getput (gl_map_t map, const void *key, const void *value, const void **oldvaluep); #endif -GL_XMAP_INLINE gl_map_t +GL_XMAP_INLINE +/*_GL_ATTRIBUTE_DEALLOC (gl_map_free, 1)*/ +_GL_ATTRIBUTE_RETURNS_NONNULL +gl_map_t gl_map_create_empty (gl_map_implementation_t implementation, gl_mapkey_equals_fn equals_fn, gl_mapkey_hashcode_fn hashcode_fn, diff --git a/lib/gl_xomap.h b/lib/gl_xomap.h index a74ac6d..bc21528 100644 --- a/lib/gl_xomap.h +++ b/lib/gl_xomap.h @@ -41,13 +41,18 @@ extern "C" { extern gl_omap_t gl_omap_create_empty (gl_omap_implementation_t implementation, gl_mapkey_compar_fn compar_fn, gl_mapkey_dispose_fn kdispose_fn, - gl_mapvalue_dispose_fn vdispose_fn); + gl_mapvalue_dispose_fn vdispose_fn) + /*_GL_ATTRIBUTE_DEALLOC (gl_omap_free, 1)*/ + _GL_ATTRIBUTE_RETURNS_NONNULL; extern bool gl_omap_put (gl_omap_t map, const void *key, const void *value); extern bool gl_omap_getput (gl_omap_t map, const void *key, const void *value, const void **oldvaluep); #endif -GL_XOMAP_INLINE gl_omap_t +GL_XOMAP_INLINE +/*_GL_ATTRIBUTE_DEALLOC (gl_omap_free, 1)*/ +_GL_ATTRIBUTE_RETURNS_NONNULL +gl_omap_t gl_omap_create_empty (gl_omap_implementation_t implementation, gl_mapkey_compar_fn compar_fn, gl_mapkey_dispose_fn kdispose_fn, diff --git a/lib/gl_xoset.h b/lib/gl_xoset.h index a2c7930..ced666d 100644 --- a/lib/gl_xoset.h +++ b/lib/gl_xoset.h @@ -40,11 +40,16 @@ extern "C" { #if 0 /* These are defined inline below. */ extern gl_oset_t gl_oset_create_empty (gl_oset_implementation_t implementation, gl_setelement_compar_fn compar_fn, - gl_setelement_dispose_fn dispose_fn); + gl_setelement_dispose_fn dispose_fn) + /*_GL_ATTRIBUTE_DEALLOC (gl_oset_free, 1)*/ + _GL_ATTRIBUTE_RETURNS_NONNULL; extern bool gl_oset_add (gl_oset_t set, const void *elt); #endif -GL_XOSET_INLINE gl_oset_t +GL_XOSET_INLINE +/*_GL_ATTRIBUTE_DEALLOC (gl_oset_free, 1)*/ +_GL_ATTRIBUTE_RETURNS_NONNULL +gl_oset_t gl_oset_create_empty (gl_oset_implementation_t implementation, gl_setelement_compar_fn compar_fn, gl_setelement_dispose_fn dispose_fn) diff --git a/lib/gl_xset.h b/lib/gl_xset.h index 88fa483..5206ba0 100644 --- a/lib/gl_xset.h +++ b/lib/gl_xset.h @@ -41,11 +41,16 @@ extern "C" { extern gl_set_t gl_set_create_empty (gl_set_implementation_t implementation, gl_setelement_equals_fn equals_fn, gl_setelement_hashcode_fn hashcode_fn, - gl_setelement_dispose_fn dispose_fn); + gl_setelement_dispose_fn dispose_fn) + /*_GL_ATTRIBUTE_DEALLOC (gl_set_free, 1)*/ + _GL_ATTRIBUTE_RETURNS_NONNULL; extern bool gl_set_add (gl_set_t set, const void *elt); #endif -GL_XSET_INLINE gl_set_t +GL_XSET_INLINE +/*_GL_ATTRIBUTE_DEALLOC (gl_set_free, 1)*/ +_GL_ATTRIBUTE_RETURNS_NONNULL +gl_set_t gl_set_create_empty (gl_set_implementation_t implementation, gl_setelement_equals_fn equals_fn, gl_setelement_hashcode_fn hashcode_fn, diff --git a/lib/gl_xsublist.h b/lib/gl_xsublist.h index cae165e..2427caa 100644 --- a/lib/gl_xsublist.h +++ b/lib/gl_xsublist.h @@ -37,7 +37,10 @@ extern "C" { /* These functions are thin wrappers around the corresponding functions with _nx_ infix from gl_sublist.h. Upon out-of-memory, they invoke xalloc_die (), instead of returning an error indicator. */ -GL_XSUBLIST_INLINE gl_list_t +GL_XSUBLIST_INLINE +/*_GL_ATTRIBUTE_DEALLOC (gl_list_free, 1)*/ +_GL_ATTRIBUTE_RETURNS_NONNULL +gl_list_t gl_sublist_create (gl_list_t whole_list, size_t start_index, size_t end_index) { gl_list_t result = gl_sublist_nx_create (whole_list, start_index, end_index);
