[glib: 2/4] gatomic: Fix strict aliasing problems with g_atomic_pointer_{get, set}()



commit 3251cce524dbde48e0e5ea0df3169f76e10d0794
Author: Philip Withnall <withnall endlessm com>
Date:   Mon Oct 7 16:23:02 2019 +0100

    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>

 glib/gatomic.h | 31 ++++++++++++++++++++++++++-----
 1 file changed, 26 insertions(+), 5 deletions(-)
---
diff --git a/glib/gatomic.h b/glib/gatomic.h
index 61a99adf2..304e855b1 100644
--- a/glib/gatomic.h
+++ b/glib/gatomic.h
@@ -103,20 +103,41 @@ G_END_DECLS
     __atomic_store ((gint *)(atomic), &gais_temp, __ATOMIC_SEQ_CST);         \
   }))
 
+#if defined(g_has_typeof)
 #define g_atomic_pointer_get(atomic) \
   (G_GNUC_EXTENSION ({                                                       \
     G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer));                 \
-    gpointer gapg_temp;                                                      \
-    __atomic_load ((gpointer *)(atomic), &gapg_temp, __ATOMIC_SEQ_CST);      \
-    gapg_temp;                                                               \
+    __typeof__(*(atomic)) gapg_temp_newval;                                  \
+    __typeof__((atomic)) gapg_temp_atomic = (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 = (gpointer)(newval);                                 \
+    __typeof__((atomic)) gaps_temp_atomic = (atomic);                        \
+    __typeof__(*(atomic)) gaps_temp_newval = (newval);                       \
     (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) */
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]