@@ -246,26 +246,42 @@ typedef struct ecs_allocator_t ecs_allocator_t;
246246
247247#define ECS_SIZEOF (T ) ECS_CAST(ecs_size_t, sizeof(T))
248248
249- /* Use alignof in C++, or a trick in C. */
250- #ifdef __cplusplus
251- #define ECS_ALIGNOF (T ) static_cast<int64_t>(alignof(T))
252- #elif defined(ECS_TARGET_MSVC )
253- #define ECS_ALIGNOF (T ) (int64_t)__alignof(T)
254- #else
255- /* Use the struct trick since on 32-bit platforms __alignof__ can return different
256- * results than C++'s alignof. This is illustrated when doing:
257- *
249+ /* Alignment macros:
250+ * - Use alignof in C++
251+ * - Use _Alignof in C11 and above
252+ * - Use __alignof__ on 64 bit platforms on clang/gcc
253+ * - Use struct trick on other compilers/32 bit
254+ *
255+ * The reason the code doesn't use the struct trick everywhere is because this
256+ * can cause ASAN errors (runtime error: member access within null pointer).
257+ *
258+ * The reason why the clang/gcc __alignof__ feature is not used on 32 bit, is
259+ * because its behavior is different than C++:
260+ *
258261 * __alignof__(uint64_t) == 8 on 32-bit platforms
259262 * alignof(uint64_t) == 4 on 32-bit platforms
260- *
263+ *
261264 * typedef struct {
262265 * uint64_t value;
263266 * } Foo;
264267 *
265268 * __alignof__(Foo) == 4 on 32-bit platforms
266269 * alignof(Foo) == 4 on 32-bit platforms
267270 */
271+ #ifdef __cplusplus
272+ #define ECS_ALIGNOF (T ) static_cast<int64_t>(alignof(T))
273+ #elif defined(ECS_TARGET_MSVC )
274+ #define ECS_ALIGNOF (T ) (int64_t)__alignof(T)
275+ #elif __STDC_VERSION__ >= 201112L
276+ #define ECS_ALIGNOF (T ) ((int64_t)_Alignof(T))
277+ #else
268278#define ECS_ALIGNOF (T ) ((int64_t)(size_t)&((struct { char c; T d; } *)0)->d)
279+ #if defined(ECS_TARGET_GNU ) || defined(ECS_TARGET_CLANG )
280+ #if __SIZEOF_POINTER__ == 8
281+ #undef ECS_ALIGNOF
282+ #define ECS_ALIGNOF (T ) (int64_t)__alignof__(T)
283+ #endif
284+ #endif
269285#endif
270286
271287#ifndef FLECS_NO_ALWAYS_INLINE
0 commit comments