summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Withnall <philip@tecnocode.co.uk>2018-07-17 09:23:29 +0000
committerPhilip Withnall <philip@tecnocode.co.uk>2018-07-17 09:23:29 +0000
commit4dc6a01241f4313f8fad866cbcb5a3fd703b9974 (patch)
treefe5919156c135f1e493b3d2ae3d4d3acd8b6e69a
parent8d2d0a8aa134189daf2f5cd31a97cc8e517080bf (diff)
parentf9a9902aac826ab4aecc25f6eb533a418a4fa559 (diff)
downloadglib-4dc6a01241f4313f8fad866cbcb5a3fd703b9974.tar.gz
Merge branch 'type-safe-g-clear-pointer-1425' into 'master'
Type safe g clear pointer 1425 Closes #1425 See merge request GNOME/glib!177
-rw-r--r--glib/gmem.h11
-rw-r--r--glib/tests/utils.c17
-rw-r--r--gobject/gobject.c2
-rw-r--r--gobject/gobject.h2
-rw-r--r--gobject/tests/reference.c2
5 files changed, 31 insertions, 3 deletions
diff --git a/glib/gmem.h b/glib/gmem.h
index 5cccb045c..302809478 100644
--- a/glib/gmem.h
+++ b/glib/gmem.h
@@ -110,6 +110,16 @@ gpointer g_try_realloc_n (gpointer mem,
gsize n_blocks,
gsize n_block_bytes) G_GNUC_WARN_UNUSED_RESULT;
+#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) && !defined(__cplusplus) && GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_58
+#define g_clear_pointer(pp, destroy) \
+ G_STMT_START { \
+ G_STATIC_ASSERT (sizeof *(pp) == sizeof (gpointer)); \
+ __typeof__(*(pp)) _ptr = *(pp); \
+ *(pp) = NULL; \
+ if (_ptr) \
+ (destroy) (_ptr); \
+ } G_STMT_END
+#else /* __GNUC__ */
#define g_clear_pointer(pp, destroy) \
G_STMT_START { \
G_STATIC_ASSERT (sizeof *(pp) == sizeof (gpointer)); \
@@ -127,6 +137,7 @@ gpointer g_try_realloc_n (gpointer mem,
_destroy (_p); \
} \
} G_STMT_END
+#endif /* __GNUC__ */
/**
* g_steal_pointer:
diff --git a/glib/tests/utils.c b/glib/tests/utils.c
index 7f8edd8da..95c6138e4 100644
--- a/glib/tests/utils.c
+++ b/glib/tests/utils.c
@@ -517,6 +517,22 @@ test_clear_pointer (void)
g_assert (a == NULL);
}
+/* Test that g_clear_pointer() works with a GDestroyNotify which contains a cast.
+ * See https://gitlab.gnome.org/GNOME/glib/issues/1425 */
+static void
+test_clear_pointer_cast (void)
+{
+ GHashTable *hash_table = NULL;
+
+ hash_table = g_hash_table_new (g_str_hash, g_str_equal);
+
+ g_assert_nonnull (hash_table);
+
+ g_clear_pointer (&hash_table, (void (*) (GHashTable *)) g_hash_table_destroy);
+
+ g_assert_null (hash_table);
+}
+
static int obj_count;
static void
@@ -656,6 +672,7 @@ main (int argc,
g_test_add_func ("/utils/specialdir", test_special_dir);
g_test_add_func ("/utils/specialdir/desktop", test_desktop_special_dir);
g_test_add_func ("/utils/clear-pointer", test_clear_pointer);
+ g_test_add_func ("/utils/clear-pointer-cast", test_clear_pointer_cast);
g_test_add_func ("/utils/take-pointer", test_take_pointer);
g_test_add_func ("/utils/clear-source", test_clear_source);
g_test_add_func ("/utils/misc-mem", test_misc_mem);
diff --git a/gobject/gobject.c b/gobject/gobject.c
index 555ca3fae..efb8ecab5 100644
--- a/gobject/gobject.c
+++ b/gobject/gobject.c
@@ -3378,7 +3378,7 @@ g_object_unref (gpointer _object)
**/
#undef g_clear_object
void
-g_clear_object (volatile GObject **object_ptr)
+g_clear_object (GObject **object_ptr)
{
g_clear_pointer (object_ptr, g_object_unref);
}
diff --git a/gobject/gobject.h b/gobject/gobject.h
index 838046fe0..9abe87330 100644
--- a/gobject/gobject.h
+++ b/gobject/gobject.h
@@ -668,7 +668,7 @@ G_STMT_START { \
G_OBJECT_WARN_INVALID_PSPEC ((object), "property", (property_id), (pspec))
GLIB_AVAILABLE_IN_ALL
-void g_clear_object (volatile GObject **object_ptr);
+void g_clear_object (GObject **object_ptr);
#define g_clear_object(object_ptr) g_clear_pointer ((object_ptr), g_object_unref)
/**
diff --git a/gobject/tests/reference.c b/gobject/tests/reference.c
index b05150e96..9508ee741 100644
--- a/gobject/tests/reference.c
+++ b/gobject/tests/reference.c
@@ -132,7 +132,7 @@ test_clear (void)
static void
test_clear_function (void)
{
- volatile GObject *o = NULL;
+ GObject *o = NULL;
GObject *tmp;
(g_clear_object) (&o);