X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=src%2Fcommon%2Fmacros.hpp;h=a4ff6504d078807056330c4fd8f3e25b3a05f2ad;hb=f12e33ba4926d519a81baa388384fc54afde3985;hp=d2b78200e7ebab9e7e6faffd16749f2a88082bae;hpb=c9e313bc594f40a86eed237dce222c0fc99c957f;p=lttng-tools.git diff --git a/src/common/macros.hpp b/src/common/macros.hpp index d2b78200e..a4ff6504d 100644 --- a/src/common/macros.hpp +++ b/src/common/macros.hpp @@ -9,10 +9,13 @@ #ifndef _MACROS_H #define _MACROS_H -#include +#include + #include +#include #include -#include + +#include /* * Takes a pointer x and transform it so we can use it to access members @@ -36,15 +39,190 @@ */ #define LTTNG_REF(x) ((typeof(*x) *)(x)) +#ifdef NDEBUG +/* +* Force usage of the assertion condition to prevent unused variable warnings +* when `assert()` are disabled by the `NDEBUG` definition. +*/ +# define LTTNG_ASSERT(_cond) ((void) sizeof((void) (_cond), 0)) +#else +# include +# define LTTNG_ASSERT(_cond) assert(_cond) +#endif + /* * Memory allocation zeroed */ + static inline -void *zmalloc(size_t len) +void *zmalloc_internal(size_t size) { - return calloc(1, len); + return calloc(1, size); } +template +struct can_malloc +{ + /* + * gcc versions before 5.0 lack some type traits defined in C++11. + * Since in this instance we use the trait to prevent misuses + * of malloc (and statically assert) and not to generate different + * code based on this property, simply set value to true and allow + * the code to compile. Anyone using a contemporary compiler will + * catch the error. + */ +#if __GNUG__ && __GNUC__ < 5 + static constexpr bool value = true; +#else + static constexpr bool value = std::is_trivially_constructible::value; +#endif +}; + +/* + * Malloc and zero-initialize an object of type T, asserting that T can be + * safely malloc-ed (is trivially constructible). + */ +template +T *zmalloc() +{ + static_assert (can_malloc::value, "type can be malloc'ed"); + return (T *) zmalloc_internal(sizeof(T)); +} + +/* + * Malloc and zero-initialize a buffer of size `size`, asserting that type T + * can be safely malloc-ed (is trivially constructible). + */ +template +T *zmalloc(size_t size) +{ + static_assert (can_malloc::value, "type can be malloc'ed"); + LTTNG_ASSERT(size >= sizeof(T)); + return (T *) zmalloc_internal(size); +} + +/* + * Malloc and zero-initialize an array of `nmemb` elements of type T, + * asserting that T can be safely malloc-ed (is trivially constructible). + */ +template +T *calloc(size_t nmemb) +{ + static_assert (can_malloc::value, "type can be malloc'ed"); + return (T *) zmalloc_internal(nmemb * sizeof(T)); +} + +/* + * Malloc an object of type T, asserting that T can be safely malloc-ed (is + * trivially constructible). + */ +template +T *malloc() +{ + static_assert (can_malloc::value, "type can be malloc'ed"); + return (T *) malloc(sizeof(T)); +} + +/* + * Malloc a buffer of size `size`, asserting that type T can be safely + * malloc-ed (is trivially constructible). + */ +template +T *malloc(size_t size) +{ + static_assert (can_malloc::value, "type can be malloc'ed"); + return (T *) malloc(size); +} + +/* + * Prevent using `free` on types that are non-POD. + * + * Declare a delete prototype of free if the parameter type is not safe to free + * (non-POD). + * + * If the parameter is a pointer to void, we can't check if what is pointed + * to is safe to free or not, as we don't know what is pointed to. Ideally, + * all calls to free would be with a typed pointer, but there are too many + * instances of passing a pointer to void to enforce that right now. So allow + * pointers to void, these will not be checked. + */ + +template +struct can_free +{ + /* + * gcc versions before 5.0 lack some type traits defined in C++11. + * Since in this instance we use the trait to prevent misuses + * of free (and statically assert) and not to generate different + * code based on this property, simply set value to true and allow + * the code to compile. Anyone using a contemporary compiler will + * catch the error. + */ +#if __GNUG__ && __GNUC__ < 5 + static constexpr bool value = true; +#else + static constexpr bool value = std::is_trivially_destructible::value || std::is_void::value; +#endif +}; + +template::value>::type> +void free(T *p) = delete; + +template +struct can_memset +{ + static constexpr bool value = std::is_pod::value || std::is_void::value; +}; + +template ::value>::type> +void *memset(T *s, int c, size_t n) = delete; + +template +struct can_memcpy +{ + /* + * gcc versions before 5.0 lack some type traits defined in C++11. + * Since in this instance we use the trait to prevent misuses + * of memcpy (and statically assert) and not to generate different + * code based on this property, simply set value to true and allow + * the code to compile. Anyone using a contemporary compiler will + * catch the error. + */ +#if __GNUG__ && __GNUC__ < 5 + static constexpr bool value = true; +#else + static constexpr bool value = std::is_trivially_copyable::value; +#endif +}; + +template ::value>::type, + typename = typename std::enable_if::value>::type> +void *memcpy(T *d, const U *s, size_t n) = delete; + +template +struct can_memmove +{ + /* + * gcc versions before 5.0 lack some type traits defined in C++11. + * Since in this instance we use the trait to prevent misuses + * of memmove (and statically assert) and not to generate different + * code based on this property, simply set value to true and allow + * the code to compile. Anyone using a contemporary compiler will + * catch the error. + */ +#if __GNUG__ && __GNUC__ < 5 + static constexpr bool value = true; +#else + static constexpr bool value = std::is_trivially_copyable::value; +#endif +}; + +template ::value>::type, + typename = typename std::enable_if::value>::type> +void *memmove(T *d, const U *s, size_t n) = delete; + #ifndef ARRAY_SIZE #define ARRAY_SIZE(array) (sizeof(array) / (sizeof((array)[0]))) #endif @@ -130,15 +308,4 @@ int lttng_strncpy(char *dst, const char *src, size_t dst_len) return 0; } -#ifdef NDEBUG -/* -* Force usage of the assertion condition to prevent unused variable warnings -* when `assert()` are disabled by the `NDEBUG` definition. -*/ -# define LTTNG_ASSERT(_cond) ((void) sizeof((void) (_cond), 0)) -#else -# include -# define LTTNG_ASSERT(_cond) assert(_cond) -#endif - #endif /* _MACROS_H */