Commit 9c5dafed authored by Fabio Baltieri's avatar Fabio Baltieri Committed by Carles Cufi
Browse files

util: add type checking to CONTAINER_OF

Add a SAME_TYPE checking macro and use it to add type validation to
CONTAINER_OF. This is inspired by the Linux container_of implementation.

The check is inhibited when using C++ as __builtin_types_compatible_p is
not available there.

Signed-off-by: default avatarFabio Baltieri <fabiobaltieri@google.com>
parent 48c56ceb
Loading
Loading
Loading
Loading
+26 −1
Changes for include/zephyr/sys/util.h: 26 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#define ZEPHYR_INCLUDE_SYS_UTIL_H_

#include <zephyr/sys/util_macro.h>
#include <zephyr/toolchain/common.h>

/* needs to be outside _ASMLANGUAGE so 'true' and 'false' can turn
 * into '1' and '0' for asm or linker scripts
@@ -201,6 +202,27 @@ extern "C" {
		(POINTER_TO_UINT(ptr) - POINTER_TO_UINT(array)) / sizeof((array)[0]);              \
	})

/**
 * @brief Validate if two entities have a compatible type
 *
 * @param a the first entity to be compared
 * @param a the second entity to be compared
 * @return 1 if the two elements are compatible, 0 if they are not
 */
#define SAME_TYPE(a, b) __builtin_types_compatible_p(__typeof__(a), __typeof__(b))

/**
 * @brief Validate CONTAINER_OF parameters, only applies to C mode.
 */
#ifndef __cplusplus
#define CONTAINER_OF_VALIDATE(ptr, type, field)               \
	BUILD_ASSERT(SAME_TYPE(*(ptr), ((type *)0)->field) || \
		     SAME_TYPE(*(ptr), void),                 \
		     "pointer type mismatch in CONTAINER_OF");
#else
#define CONTAINER_OF_VALIDATE(ptr, type, field)
#endif

/**
 * @brief Get a pointer to a structure containing the element
 *
@@ -223,7 +245,10 @@ extern "C" {
 * @return a pointer to the structure that contains @p ptr
 */
#define CONTAINER_OF(ptr, type, field)                               \
	((type *)(((char *)(ptr)) - offsetof(type, field)))
	({                                                           \
		CONTAINER_OF_VALIDATE(ptr, type, field)              \
		((type *)(((char *)(ptr)) - offsetof(type, field))); \
	})

/**
 * @brief Value of @p x rounded up to the next multiple of @p align.