mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-08-08 18:24:04 +02:00
gatomic: Fix strict aliasing problems with g_atomic_pointer_{get,set}()
Casting pointer types around is a bit fiddly when you also end up dereferencing them. Take advantage of the fact that the `__atomic_load()` and `__atomic_store()` built-ins are polymorphic, and use `__typeof__()` to ensure that the atomic pointer macros use the caller-provided types internally, and hence any type mismatches are entirely the caller’s fault rather than ours. This also means that the `__atomic_{load,store}()` built-ins have the right alignment and width data from the caller-provided types, in case that’s needed. Signed-off-by: Philip Withnall <withnall@endlessm.com>
This commit is contained in:
@@ -103,20 +103,41 @@ G_END_DECLS
|
|||||||
__atomic_store ((gint *)(atomic), &gais_temp, __ATOMIC_SEQ_CST); \
|
__atomic_store ((gint *)(atomic), &gais_temp, __ATOMIC_SEQ_CST); \
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
#if defined(g_has_typeof)
|
||||||
#define g_atomic_pointer_get(atomic) \
|
#define g_atomic_pointer_get(atomic) \
|
||||||
(G_GNUC_EXTENSION ({ \
|
(G_GNUC_EXTENSION ({ \
|
||||||
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
|
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
|
||||||
gpointer gapg_temp; \
|
__typeof__(*(atomic)) gapg_temp_newval; \
|
||||||
__atomic_load ((gpointer *)(atomic), &gapg_temp, __ATOMIC_SEQ_CST); \
|
__typeof__((atomic)) gapg_temp_atomic = (atomic); \
|
||||||
gapg_temp; \
|
__atomic_load (gapg_temp_atomic, &gapg_temp_newval, __ATOMIC_SEQ_CST); \
|
||||||
|
gapg_temp_newval; \
|
||||||
}))
|
}))
|
||||||
#define g_atomic_pointer_set(atomic, newval) \
|
#define g_atomic_pointer_set(atomic, newval) \
|
||||||
(G_GNUC_EXTENSION ({ \
|
(G_GNUC_EXTENSION ({ \
|
||||||
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
|
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
|
||||||
gpointer gaps_temp = (gpointer)(newval); \
|
__typeof__((atomic)) gaps_temp_atomic = (atomic); \
|
||||||
|
__typeof__(*(atomic)) gaps_temp_newval = (newval); \
|
||||||
(void) (0 ? (gpointer) *(atomic) : NULL); \
|
(void) (0 ? (gpointer) *(atomic) : NULL); \
|
||||||
__atomic_store ((gpointer *)(atomic), &gaps_temp, __ATOMIC_SEQ_CST); \
|
__atomic_store (gaps_temp_atomic, &gaps_temp_newval, __ATOMIC_SEQ_CST); \
|
||||||
}))
|
}))
|
||||||
|
#else /* if !defined(g_has_typeof) */
|
||||||
|
#define g_atomic_pointer_get(atomic) \
|
||||||
|
(G_GNUC_EXTENSION ({ \
|
||||||
|
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
|
||||||
|
gpointer gapg_temp_newval; \
|
||||||
|
gpointer *gapg_temp_atomic = (gpointer *)(atomic); \
|
||||||
|
__atomic_load (gapg_temp_atomic, &gapg_temp_newval, __ATOMIC_SEQ_CST); \
|
||||||
|
gapg_temp_newval; \
|
||||||
|
}))
|
||||||
|
#define g_atomic_pointer_set(atomic, newval) \
|
||||||
|
(G_GNUC_EXTENSION ({ \
|
||||||
|
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
|
||||||
|
gpointer *gaps_temp_atomic = (gpointer *)(atomic); \
|
||||||
|
gpointer gaps_temp_newval = (gpointer)(newval); \
|
||||||
|
(void) (0 ? (gpointer) *(atomic) : NULL); \
|
||||||
|
__atomic_store (gaps_temp_atomic, &gaps_temp_newval, __ATOMIC_SEQ_CST); \
|
||||||
|
}))
|
||||||
|
#endif /* !defined(g_has_typeof) */
|
||||||
|
|
||||||
#else /* defined(__ATOMIC_SEQ_CST) */
|
#else /* defined(__ATOMIC_SEQ_CST) */
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user