#include <stdlib.h>
#include <string.h>
+#include <memory>
+#include <pthread.h>
#include <type_traits>
/*
* memory using malloc(), we must use generic accessors for compat in order to
* *not* use a function to access members and not the variable name.
*/
-#define LTTNG_REF(x) ((typeof(*x) *)(x))
+#define LTTNG_REF(x) ((typeof(*(x)) *) (x))
#ifdef NDEBUG
/*
template <typename T>
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<T>::value;
+#endif
};
/*
T *zmalloc()
{
static_assert (can_malloc<T>::value, "type can be malloc'ed");
- return (T *) zmalloc_internal(sizeof(T));
+ return (T *) zmalloc_internal(sizeof(T)); /* NOLINT sizeof potentially used on a pointer. */
}
/*
T *calloc(size_t nmemb)
{
static_assert (can_malloc<T>::value, "type can be malloc'ed");
- return (T *) zmalloc_internal(nmemb * sizeof(T));
+ return (T *) zmalloc_internal(nmemb * sizeof(T)); /* NOLINT sizeof potentially used on a pointer. */
}
/*
template<typename T>
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<T>::value || std::is_void<T>::value;
+#endif
};
template<typename T, typename = typename std::enable_if<!can_free<T>::value>::type>
template<typename T>
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<T>::value;
+#endif
};
template <typename T, typename U,
template<typename T>
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<T>::value;
+#endif
};
template <typename T, typename U,
#define ARRAY_SIZE(array) (sizeof(array) / (sizeof((array)[0])))
#endif
-#ifndef container_of
-#define container_of(ptr, type, member) \
- ({ \
- const typeof(((type *)NULL)->member) * __ptr = (ptr); \
- (type *)((char *)__ptr - offsetof(type, member)); \
- })
-#endif
-
#ifndef LTTNG_PACKED
#define LTTNG_PACKED __attribute__((__packed__))
#endif
#define member_sizeof(type, field) sizeof(((type *) 0)->field)
-#define ASSERT_LOCKED(lock) LTTNG_ASSERT(pthread_mutex_trylock(&lock))
+#define ASSERT_LOCKED(lock) LTTNG_ASSERT(pthread_mutex_trylock(&(lock)))
#define ASSERT_RCU_READ_LOCKED(lock) LTTNG_ASSERT(rcu_read_ongoing())
/* Attribute suitable to tag functions as having printf()-like arguments. */
# define DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL \
_Pragma("GCC diagnostic ignored \"-Wformat-nonliteral\"")
# define DIAGNOSTIC_IGNORE_LOGICAL_OP
+# define DIAGNOSTIC_IGNORE_DUPLICATED_BRANCHES
+# define DIAGNOSTIC_IGNORE_INVALID_OFFSETOF
+ _Pragma("GCC diagnostic ignored \"-Winvalid-offsetof\"")
#else
/* GCC */
# define DIAGNOSTIC_IGNORE_SUGGEST_ATTRIBUTE_FORMAT \
_Pragma("GCC diagnostic ignored \"-Wformat-nonliteral\"")
# define DIAGNOSTIC_IGNORE_LOGICAL_OP \
_Pragma("GCC diagnostic ignored \"-Wlogical-op\"")
+#if __GNUG__ && __GNUC__ >= 7
+# define DIAGNOSTIC_IGNORE_DUPLICATED_BRANCHES \
+ _Pragma("GCC diagnostic ignored \"-Wduplicated-branches\"")
+#else
+# define DIAGNOSTIC_IGNORE_DUPLICATED_BRANCHES
+#endif /* __GNUG__ && __GNUC__ >= 7 */
+# define DIAGNOSTIC_IGNORE_INVALID_OFFSETOF \
+ _Pragma("GCC diagnostic ignored \"-Winvalid-offsetof\"")
#endif
/* Used to make specific C++ functions to C code. */
return 0;
}
+namespace lttng {
+namespace utils {
+template <class Parent, class Member>
+Parent *container_of(const Member *member, const Member Parent::*ptr_to_member)
+{
+ const Parent *dummy_parent = nullptr;
+ auto *offset_of_member = reinterpret_cast<const char *>(&(dummy_parent->*ptr_to_member));
+ auto address_of_parent = reinterpret_cast<const char *>(member) - offset_of_member;
+
+ return reinterpret_cast<Parent *>(address_of_parent);
+}
+} /* namespace utils */
+} /* namespace lttng */
+
#endif /* _MACROS_H */