summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Withnall <philip@tecnocode.co.uk>2020-10-15 08:52:47 +0000
committerPhilip Withnall <philip@tecnocode.co.uk>2020-10-15 08:52:47 +0000
commite2e8339e0ac4f5a6a972af85c8a09e99c50a564b (patch)
treeb8809c496d1d3e19ae1b8e30bbc2181727c0bbe2
parent31bca17f52ee1170953bd166d4066a1a037b5d71 (diff)
parent0d81443ec025b832d3f072a25bdc8e74c13a3919 (diff)
downloadglib-e2e8339e0ac4f5a6a972af85c8a09e99c50a564b.tar.gz
Merge branch 'typeof' into 'master'
Use C++11 decltype where possible See merge request GNOME/glib!1575
-rw-r--r--docs/reference/glib/glib-sections.txt2
-rw-r--r--gio/gcredentials.c2
-rw-r--r--glib/gatomic.h66
-rw-r--r--glib/gmacros.h8
-rw-r--r--glib/gmem.h26
-rw-r--r--glib/grcbox.h18
-rw-r--r--glib/tests/cxx.cpp64
-rw-r--r--glib/tests/meson.build3
-rw-r--r--gobject/gobject.h6
9 files changed, 145 insertions, 50 deletions
diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt
index e96e6c86b..02bb2ba50 100644
--- a/docs/reference/glib/glib-sections.txt
+++ b/docs/reference/glib/glib-sections.txt
@@ -730,7 +730,7 @@ GLIB_UNAVAILABLE_TYPE
G_ANALYZER_ANALYZING
G_ANALYZER_NORETURN
g_autoptr_cleanup_generic_gfree
-g_has_typeof
+glib_typeof
g_macro__has_attribute
g_macro__has_builtin
g_macro__has_feature
diff --git a/gio/gcredentials.c b/gio/gcredentials.c
index 146829e7c..9423f9ef9 100644
--- a/gio/gcredentials.c
+++ b/gio/gcredentials.c
@@ -225,7 +225,7 @@ g_credentials_to_string (GCredentials *credentials)
{
GString *ret;
#if G_CREDENTIALS_USE_APPLE_XUCRED
- __typeof__(credentials->native.cr_ngroups) i;
+ glib_typeof (credentials->native.cr_ngroups) i;
#endif
g_return_val_if_fail (G_IS_CREDENTIALS (credentials), NULL);
diff --git a/glib/gatomic.h b/glib/gatomic.h
index 6bf41bb74..bb1435c70 100644
--- a/glib/gatomic.h
+++ b/glib/gatomic.h
@@ -103,24 +103,24 @@ 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)); \
- __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)); \
- __typeof__((atomic)) gaps_temp_atomic = (atomic); \
- __typeof__(*(atomic)) gaps_temp_newval = (newval); \
- (void) (0 ? (gpointer) *(atomic) : NULL); \
- __atomic_store (gaps_temp_atomic, &gaps_temp_newval, __ATOMIC_SEQ_CST); \
- }))
-#else /* if !defined(g_has_typeof) */
+#if defined(glib_typeof)
+#define g_atomic_pointer_get(atomic) \
+ (G_GNUC_EXTENSION ({ \
+ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
+ glib_typeof (*(atomic)) gapg_temp_newval; \
+ glib_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)); \
+ glib_typeof ((atomic)) gaps_temp_atomic = (atomic); \
+ glib_typeof (*(atomic)) gaps_temp_newval = (newval); \
+ (void) (0 ? (gpointer) * (atomic) : NULL); \
+ __atomic_store (gaps_temp_atomic, &gaps_temp_newval, __ATOMIC_SEQ_CST); \
+ }))
+#else /* if !defined(glib_typeof) */
#define g_atomic_pointer_get(atomic) \
(G_GNUC_EXTENSION ({ \
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
@@ -137,7 +137,7 @@ G_END_DECLS
(void) (0 ? (gpointer) *(atomic) : NULL); \
__atomic_store (gaps_temp_atomic, &gaps_temp_newval, __ATOMIC_SEQ_CST); \
}))
-#endif /* !defined(g_has_typeof) */
+#endif /* !defined(glib_typeof) */
#define g_atomic_int_inc(atomic) \
(G_GNUC_EXTENSION ({ \
@@ -183,14 +183,25 @@ G_END_DECLS
(guint) __atomic_fetch_xor ((atomic), (val), __ATOMIC_SEQ_CST); \
}))
+#if defined(glib_typeof)
+#define g_atomic_pointer_compare_and_exchange(atomic, oldval, newval) \
+ (G_GNUC_EXTENSION ({ \
+ G_STATIC_ASSERT (sizeof (oldval) == sizeof (gpointer)); \
+ glib_typeof ((oldval)) gapcae_oldval = (oldval); \
+ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
+ (void) (0 ? (gpointer) *(atomic) : NULL); \
+ __atomic_compare_exchange_n ((atomic), &gapcae_oldval, (newval), FALSE, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ? TRUE : FALSE; \
+ }))
+#else /* if !defined(glib_typeof) */
#define g_atomic_pointer_compare_and_exchange(atomic, oldval, newval) \
(G_GNUC_EXTENSION ({ \
G_STATIC_ASSERT (sizeof (oldval) == sizeof (gpointer)); \
- __typeof__ ((oldval)) gapcae_oldval = (oldval); \
+ gpointer gapcae_oldval = (gpointer)(oldval); \
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
(void) (0 ? (gpointer) *(atomic) : NULL); \
__atomic_compare_exchange_n ((atomic), &gapcae_oldval, (newval), FALSE, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ? TRUE : FALSE; \
}))
+#endif /* defined(glib_typeof) */
#define g_atomic_pointer_add(atomic, val) \
(G_GNUC_EXTENSION ({ \
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
@@ -283,14 +294,25 @@ G_END_DECLS
__asm__ __volatile__ ("" : : : "memory"); \
gapg_result; \
}))
+#if defined(glib_typeof)
+#define g_atomic_pointer_set(atomic, newval) \
+ (G_GNUC_EXTENSION ({ \
+ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
+ (void) (0 ? (gpointer) *(atomic) : NULL); \
+ __sync_synchronize (); \
+ __asm__ __volatile__ ("" : : : "memory"); \
+ *(atomic) = (glib_typeof (*(atomic))) (gsize) (newval); \
+ }))
+#else /* if !defined(glib_typeof) */
#define g_atomic_pointer_set(atomic, newval) \
(G_GNUC_EXTENSION ({ \
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
(void) (0 ? (gpointer) *(atomic) : NULL); \
__sync_synchronize (); \
__asm__ __volatile__ ("" : : : "memory"); \
- *(atomic) = (__typeof__ (*(atomic))) (gsize) (newval); \
+ *(atomic) = (gpointer) (gsize) (newval); \
}))
+#endif /* defined(glib_typeof) */
#define g_atomic_int_inc(atomic) \
(G_GNUC_EXTENSION ({ \
@@ -408,6 +430,6 @@ G_END_DECLS
#define g_atomic_pointer_xor(atomic, val) \
(g_atomic_pointer_xor ((atomic), (gsize) (val)))
-#endif /* defined(__GNUC__) && defined(G_ATOMIC_OP_USE_GCC_BUILTINS) */
+#endif /* defined(G_ATOMIC_LOCK_FREE) && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) */
#endif /* __G_ATOMIC_H__ */
diff --git a/glib/gmacros.h b/glib/gmacros.h
index d953de4c8..0dd9a41c2 100644
--- a/glib/gmacros.h
+++ b/glib/gmacros.h
@@ -231,9 +231,13 @@
*
* This symbol is private.
*/
-#undef g_has_typeof
+#undef glib_typeof
#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) && !defined(__cplusplus)
-#define g_has_typeof
+#define glib_typeof(t) __typeof__ (t)
+#elif defined(__cplusplus) && __cplusplus >= 201103L
+/* C++11 decltype() is close enough for our usage */
+#include <type_traits>
+#define glib_typeof(t) std::remove_reference<decltype (t)>::type
#endif
/*
diff --git a/glib/gmem.h b/glib/gmem.h
index 45671073b..924299b20 100644
--- a/glib/gmem.h
+++ b/glib/gmem.h
@@ -110,16 +110,18 @@ gpointer g_try_realloc_n (gpointer mem,
gsize n_blocks,
gsize n_block_bytes) G_GNUC_WARN_UNUSED_RESULT;
-#if defined(g_has_typeof) && 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)) _pp = (pp); \
- __typeof__(*(pp)) _ptr = *_pp; \
- *_pp = NULL; \
- if (_ptr) \
- (destroy) (_ptr); \
- } G_STMT_END \
+#if defined(glib_typeof) && GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_58
+#define g_clear_pointer(pp, destroy) \
+ G_STMT_START \
+ { \
+ G_STATIC_ASSERT (sizeof *(pp) == sizeof (gpointer)); \
+ glib_typeof ((pp)) _pp = (pp); \
+ glib_typeof (*(pp)) _ptr = *_pp; \
+ *_pp = NULL; \
+ if (_ptr) \
+ (destroy) (_ptr); \
+ } \
+ G_STMT_END \
GLIB_AVAILABLE_MACRO_IN_2_34
#else /* __GNUC__ */
#define g_clear_pointer(pp, destroy) \
@@ -211,8 +213,8 @@ g_steal_pointer (gpointer pp)
}
/* type safety */
-#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) && !defined(__cplusplus) && GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_58
-#define g_steal_pointer(pp) ((__typeof__(*pp)) (g_steal_pointer) (pp))
+#if defined(glib_typeof) && GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_58
+#define g_steal_pointer(pp) ((glib_typeof (*pp)) (g_steal_pointer) (pp))
#else /* __GNUC__ */
/* This version does not depend on gcc extensions, but gcc does not warn
* about incompatible-pointer-types: */
diff --git a/glib/grcbox.h b/glib/grcbox.h
index c92791260..f78f5cb3b 100644
--- a/glib/grcbox.h
+++ b/glib/grcbox.h
@@ -71,18 +71,18 @@ gsize g_atomic_rc_box_get_size (gpointer mem_block);
#define g_atomic_rc_box_new0(type) \
((type *) g_atomic_rc_box_alloc0 (sizeof (type)))
-#ifdef g_has_typeof
+#ifdef glib_typeof
/* Type check to avoid assigning references to different types */
-# define g_rc_box_acquire(mem_block) \
- ((__typeof__(mem_block)) (g_rc_box_acquire) (mem_block))
-# define g_atomic_rc_box_acquire(mem_block) \
- ((__typeof__(mem_block)) (g_atomic_rc_box_acquire) (mem_block))
+#define g_rc_box_acquire(mem_block) \
+ ((glib_typeof (mem_block)) (g_rc_box_acquire) (mem_block))
+#define g_atomic_rc_box_acquire(mem_block) \
+ ((glib_typeof (mem_block)) (g_atomic_rc_box_acquire) (mem_block))
/* Type check to avoid duplicating data to different types */
-# define g_rc_box_dup(block_size,mem_block) \
- ((__typeof__(mem_block)) (g_rc_box_dup) (block_size,mem_block))
-# define g_atomic_rc_box_dup(block_size,mem_block) \
- ((__typeof__(mem_block)) (g_atomic_rc_box_dup) (block_size,mem_block))
+#define g_rc_box_dup(block_size, mem_block) \
+ ((glib_typeof (mem_block)) (g_rc_box_dup) (block_size, mem_block))
+#define g_atomic_rc_box_dup(block_size, mem_block) \
+ ((glib_typeof (mem_block)) (g_atomic_rc_box_dup) (block_size, mem_block))
#endif
G_END_DECLS
diff --git a/glib/tests/cxx.cpp b/glib/tests/cxx.cpp
new file mode 100644
index 000000000..c423b2fbc
--- /dev/null
+++ b/glib/tests/cxx.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2020 Xavier Claessens
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib.h>
+
+typedef struct
+{
+ int dummy;
+} MyObject;
+
+static void
+test_typeof (void)
+{
+#if __cplusplus >= 201103L
+ // Test that with C++11 we don't get those kind of errors:
+ // error: invalid conversion from ‘gpointer’ {aka ‘void*’} to ‘MyObject*’ [-fpermissive]
+ MyObject *obj = g_rc_box_new0 (MyObject);
+ MyObject *obj2 = g_rc_box_acquire (obj);
+ g_assert_true (obj2 == obj);
+
+ MyObject *obj3 = g_atomic_pointer_get (&obj2);
+ g_assert_true (obj3 == obj);
+
+ MyObject *obj4 = nullptr;
+ g_atomic_pointer_set (&obj4, obj3);
+ g_assert_true (obj4 == obj);
+
+ MyObject *obj5 = nullptr;
+ g_atomic_pointer_compare_and_exchange (&obj5, nullptr, obj4);
+ g_assert_true (obj5 == obj);
+
+ MyObject *obj6 = g_steal_pointer (&obj5);
+ g_assert_true (obj6 == obj);
+
+ g_clear_pointer (&obj6, g_rc_box_release);
+ g_rc_box_release (obj);
+#else
+ g_test_skip ("This test requires C++11 compiler");
+#endif
+}
+
+int
+main (int argc, char *argv[])
+{
+ g_test_init (&argc, &argv, NULL);
+
+ g_test_add_func ("/C++/typeof", test_typeof);
+
+ return g_test_run ();
+}
diff --git a/glib/tests/meson.build b/glib/tests/meson.build
index 567f5eda4..1c78dbf08 100644
--- a/glib/tests/meson.build
+++ b/glib/tests/meson.build
@@ -14,6 +14,9 @@ glib_tests = {
'collate' : {},
'cond' : {},
'convert' : {},
+ 'cxx' : {
+ 'source' : ['cxx.cpp'],
+ },
'dataset' : {},
'date' : {},
'dir' : {},
diff --git a/gobject/gobject.h b/gobject/gobject.h
index 499329af2..bf5496c54 100644
--- a/gobject/gobject.h
+++ b/gobject/gobject.h
@@ -513,10 +513,10 @@ GLIB_AVAILABLE_IN_ALL
void g_object_remove_weak_pointer (GObject *object,
gpointer *weak_pointer_location);
-#if defined(g_has_typeof) && GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_56
+#if defined(glib_typeof) && GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_56
/* Make reference APIs type safe with macros */
-#define g_object_ref(Obj) ((__typeof__(Obj)) (g_object_ref) (Obj))
-#define g_object_ref_sink(Obj) ((__typeof__(Obj)) (g_object_ref_sink) (Obj))
+#define g_object_ref(Obj) ((glib_typeof (Obj)) (g_object_ref) (Obj))
+#define g_object_ref_sink(Obj) ((glib_typeof (Obj)) (g_object_ref_sink) (Obj))
#endif
/**