mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-09 19:06:15 +01:00
Merge branch 'atomic-older-cplusplus' into 'main'
gatomic: fix the atomic compare_and_exchange macros on older C++ standard versions See merge request GNOME/glib!2864
This commit is contained in:
commit
e90733a457
@ -27,6 +27,8 @@ if cc.has_header('pty.h')
|
||||
endif
|
||||
endif
|
||||
|
||||
test_cpp_args = test_c_args
|
||||
|
||||
if host_machine.system() == 'windows'
|
||||
common_gio_tests_deps += [iphlpapi_dep, winsock2, cc.find_library ('secur32')]
|
||||
endif
|
||||
@ -130,8 +132,19 @@ if have_cxx
|
||||
gio_tests += {
|
||||
'cxx' : {
|
||||
'source' : ['cxx.cpp'],
|
||||
'suite': ['C++'],
|
||||
},
|
||||
}
|
||||
|
||||
foreach std, arg: cxx_standards
|
||||
gio_tests += {
|
||||
'cxx-@0@'.format(std) : {
|
||||
'source' : ['cxx.cpp'],
|
||||
'suite' : ['cpp'],
|
||||
'cpp_args' : [arg],
|
||||
},
|
||||
}
|
||||
endforeach
|
||||
endif
|
||||
|
||||
test_extra_programs = {
|
||||
@ -882,6 +895,7 @@ foreach test_name, extra_args : gio_tests
|
||||
|
||||
exe = executable(test_name, [source, extra_sources],
|
||||
c_args : test_c_args + extra_args.get('c_args', []),
|
||||
cpp_args : test_cpp_args + extra_args.get('cpp_args', []),
|
||||
dependencies : common_gio_tests_deps + extra_args.get('dependencies', []),
|
||||
install_rpath : extra_args.get('install_rpath', ''),
|
||||
install_dir: installed_tests_execdir,
|
||||
|
@ -170,7 +170,7 @@ G_END_DECLS
|
||||
(void) (0 ? *(atomic) ^ *(atomic) : 1); \
|
||||
__atomic_fetch_sub ((atomic), 1, __ATOMIC_SEQ_CST) == 1; \
|
||||
}))
|
||||
#if defined(glib_typeof) && defined(__cplusplus) && __cplusplus >= 201103L
|
||||
#if defined(glib_typeof) && defined(__cplusplus)
|
||||
/* See comments below about equivalent g_atomic_pointer_compare_and_exchange()
|
||||
* shenanigans for type-safety when compiling in C++ mode. */
|
||||
#define g_atomic_int_compare_and_exchange(atomic, oldval, newval) \
|
||||
@ -180,7 +180,7 @@ G_END_DECLS
|
||||
(void) (0 ? *(atomic) ^ (newval) ^ (oldval) : 1); \
|
||||
__atomic_compare_exchange_n ((atomic), &gaicae_oldval, (newval), FALSE, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ? TRUE : FALSE; \
|
||||
}))
|
||||
#else /* if !(defined(glib_typeof) && defined(__cplusplus) && __cplusplus >= 201103L) */
|
||||
#else /* if !(defined(glib_typeof) && defined(__cplusplus)) */
|
||||
#define g_atomic_int_compare_and_exchange(atomic, oldval, newval) \
|
||||
(G_GNUC_EXTENSION ({ \
|
||||
gint gaicae_oldval = (oldval); \
|
||||
@ -230,7 +230,7 @@ G_END_DECLS
|
||||
(guint) __atomic_fetch_xor ((atomic), (val), __ATOMIC_SEQ_CST); \
|
||||
}))
|
||||
|
||||
#if defined(glib_typeof) && defined(__cplusplus) && __cplusplus >= 201103L
|
||||
#if defined(glib_typeof) && defined(__cplusplus)
|
||||
/* This is typesafe because we check we can assign oldval to the type of
|
||||
* (*atomic). Unfortunately it can only be done in C++ because gcc/clang warn
|
||||
* when atomic is volatile and not oldval, or when atomic is gsize* and oldval
|
||||
@ -247,7 +247,7 @@ G_END_DECLS
|
||||
(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) && defined(__cplusplus) && __cplusplus >= 201103L) */
|
||||
#else /* if !(defined(glib_typeof) && defined(__cplusplus) */
|
||||
#define g_atomic_pointer_compare_and_exchange(atomic, oldval, newval) \
|
||||
(G_GNUC_EXTENSION ({ \
|
||||
G_STATIC_ASSERT (sizeof (oldval) == sizeof (gpointer)); \
|
||||
|
@ -34,9 +34,12 @@
|
||||
* This symbol is private.
|
||||
*/
|
||||
#undef glib_typeof
|
||||
#if !defined(__cplusplus) && (G_GNUC_CHECK_VERSION(4, 8) || defined(__clang__))
|
||||
#if (!defined(__cplusplus) || (!defined (_MSVC_LANG) && __cplusplus < 201103L)) && \
|
||||
(G_GNUC_CHECK_VERSION(4, 8) || defined(__clang__))
|
||||
#define glib_typeof(t) __typeof__ (t)
|
||||
#elif defined(__cplusplus) && __cplusplus >= 201103L && GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_68
|
||||
#elif defined(__cplusplus) && \
|
||||
(__cplusplus >= 201103L || (defined (_MSVC_LANG) && _MSVC_LANG > 201103L)) && \
|
||||
GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_68
|
||||
/* C++11 decltype() is close enough for our usage */
|
||||
#include <type_traits>
|
||||
#define glib_typeof(t) typename std::remove_reference<decltype (t)>::type
|
||||
|
@ -27,9 +27,6 @@ typedef struct
|
||||
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);
|
||||
@ -37,12 +34,21 @@ test_typeof (void)
|
||||
MyObject *obj3 = g_atomic_pointer_get (&obj2);
|
||||
g_assert_true (obj3 == obj);
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
MyObject *obj4 = nullptr;
|
||||
#else
|
||||
MyObject *obj4 = NULL;
|
||||
#endif
|
||||
g_atomic_pointer_set (&obj4, obj3);
|
||||
g_assert_true (obj4 == obj);
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
MyObject *obj5 = nullptr;
|
||||
g_atomic_pointer_compare_and_exchange (&obj5, nullptr, obj4);
|
||||
#else
|
||||
MyObject *obj5 = NULL;
|
||||
g_atomic_pointer_compare_and_exchange (&obj5, NULL, obj4);
|
||||
#endif
|
||||
g_assert_true (obj5 == obj);
|
||||
|
||||
MyObject *obj6 = g_steal_pointer (&obj5);
|
||||
@ -50,15 +56,11 @@ test_typeof (void)
|
||||
|
||||
g_clear_pointer (&obj6, g_rc_box_release);
|
||||
g_rc_box_release (obj);
|
||||
#else
|
||||
g_test_skip ("This test requires a C++11 compiler");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
test_atomic_pointer_compare_and_exchange (void)
|
||||
{
|
||||
#if __cplusplus >= 201103L
|
||||
const gchar *str1 = "str1";
|
||||
const gchar *str2 = "str2";
|
||||
const gchar *atomic_string = str1;
|
||||
@ -68,15 +70,11 @@ test_atomic_pointer_compare_and_exchange (void)
|
||||
|
||||
g_assert_true (g_atomic_pointer_compare_and_exchange (&atomic_string, str1, str2));
|
||||
g_assert_true (atomic_string == str2);
|
||||
#else
|
||||
g_test_skip ("This test requires a C++11 compiler");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
test_atomic_pointer_compare_and_exchange_full (void)
|
||||
{
|
||||
#if __cplusplus >= 201103L
|
||||
const gchar *str1 = "str1";
|
||||
const gchar *str2 = "str2";
|
||||
const gchar *atomic_string = str1;
|
||||
@ -88,15 +86,11 @@ test_atomic_pointer_compare_and_exchange_full (void)
|
||||
g_assert_true (g_atomic_pointer_compare_and_exchange_full (&atomic_string, str1, str2, &old));
|
||||
g_assert_true (atomic_string == str2);
|
||||
g_assert_true (old == str1);
|
||||
#else
|
||||
g_test_skip ("This test requires a C++11 compiler");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
test_atomic_int_compare_and_exchange (void)
|
||||
{
|
||||
#if __cplusplus >= 201103L
|
||||
gint atomic_int = 5;
|
||||
|
||||
g_test_message ("Test that g_atomic_int_compare_and_exchange() doesn’t have "
|
||||
@ -104,15 +98,11 @@ test_atomic_int_compare_and_exchange (void)
|
||||
|
||||
g_assert_true (g_atomic_int_compare_and_exchange (&atomic_int, 5, 50));
|
||||
g_assert_cmpint (atomic_int, ==, 50);
|
||||
#else
|
||||
g_test_skip ("This test requires a C++11 compiler");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
test_atomic_int_compare_and_exchange_full (void)
|
||||
{
|
||||
#if __cplusplus >= 201103L
|
||||
gint atomic_int = 5;
|
||||
gint old_value;
|
||||
|
||||
@ -122,15 +112,11 @@ test_atomic_int_compare_and_exchange_full (void)
|
||||
g_assert_true (g_atomic_int_compare_and_exchange_full (&atomic_int, 5, 50, &old_value));
|
||||
g_assert_cmpint (atomic_int, ==, 50);
|
||||
g_assert_cmpint (old_value, ==, 5);
|
||||
#else
|
||||
g_test_skip ("This test requires a C++11 compiler");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
test_atomic_pointer_exchange (void)
|
||||
{
|
||||
#if __cplusplus >= 201103L
|
||||
const gchar *str1 = "str1";
|
||||
const gchar *str2 = "str2";
|
||||
const gchar *atomic_string = str1;
|
||||
@ -140,24 +126,17 @@ test_atomic_pointer_exchange (void)
|
||||
|
||||
g_assert_true (g_atomic_pointer_exchange (&atomic_string, str2) == str1);
|
||||
g_assert_true (atomic_string == str2);
|
||||
#else
|
||||
g_test_skip ("This test requires a C++11 compiler");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
test_atomic_int_exchange (void)
|
||||
{
|
||||
#if __cplusplus >= 201103L
|
||||
gint atomic_int = 5;
|
||||
|
||||
g_test_message ("Test that g_atomic_int_compare_and_exchange() doesn’t have "
|
||||
"any compiler warnings in C++ mode");
|
||||
|
||||
g_assert_cmpint (g_atomic_int_exchange (&atomic_int, 50), ==, 5);
|
||||
#else
|
||||
g_test_skip ("This test requires a C++11 compiler");
|
||||
#endif
|
||||
}
|
||||
|
||||
G_NO_INLINE
|
||||
@ -184,6 +163,35 @@ test_inline_no_inline_macros (void)
|
||||
g_assert_true (do_inline_this ());
|
||||
}
|
||||
|
||||
static void
|
||||
clear_boolean_ptr (gboolean *val)
|
||||
{
|
||||
*val = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
test_clear_pointer (void)
|
||||
{
|
||||
gboolean value = FALSE;
|
||||
gboolean *ptr = &value;
|
||||
|
||||
g_assert_true (ptr == &value);
|
||||
g_assert_false (value);
|
||||
g_clear_pointer (&ptr, clear_boolean_ptr);
|
||||
g_assert_null (ptr);
|
||||
g_assert_true (value);
|
||||
}
|
||||
|
||||
static void
|
||||
test_steal_pointer (void)
|
||||
{
|
||||
gpointer ptr = &ptr;
|
||||
|
||||
g_assert_true (ptr == &ptr);
|
||||
g_assert_true (g_steal_pointer (&ptr) == &ptr);
|
||||
g_assert_null (ptr);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
@ -201,6 +209,8 @@ main (int argc, char *argv[])
|
||||
g_test_add_func ("/C++/atomic-pointer-exchange", test_atomic_pointer_exchange);
|
||||
g_test_add_func ("/C++/atomic-int-exchange", test_atomic_int_exchange);
|
||||
g_test_add_func ("/C++/inlined-not-inlined-functions", test_inline_no_inline_macros);
|
||||
g_test_add_func ("/C++/clear-pointer", test_clear_pointer);
|
||||
g_test_add_func ("/C++/steal-pointer", test_steal_pointer);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
@ -159,8 +159,19 @@ if have_cxx
|
||||
glib_tests += {
|
||||
'cxx' : {
|
||||
'source' : ['cxx.cpp'],
|
||||
'suite': ['cpp'],
|
||||
}
|
||||
}
|
||||
|
||||
foreach std, arg: cxx_standards
|
||||
glib_tests += {
|
||||
'cxx-@0@'.format(std) : {
|
||||
'source' : ['cxx.cpp'],
|
||||
'suite' : ['cpp'],
|
||||
'cpp_args' : [arg],
|
||||
},
|
||||
}
|
||||
endforeach
|
||||
endif
|
||||
|
||||
if cc.get_id() != 'msvc'
|
||||
@ -255,6 +266,7 @@ test_env.set('MALLOC_CHECK_', '2')
|
||||
|
||||
test_deps = [libm, thread_dep, libglib_dep]
|
||||
test_cargs = ['-DG_LOG_DOMAIN="GLib"', '-UG_DISABLE_ASSERT']
|
||||
test_cpp_args = test_cargs
|
||||
|
||||
foreach test_name, extra_args : glib_tests
|
||||
source = extra_args.get('source', test_name + '.c')
|
||||
@ -276,6 +288,7 @@ foreach test_name, extra_args : glib_tests
|
||||
|
||||
exe = executable(test_name, source,
|
||||
c_args : test_cargs + extra_args.get('c_args', []),
|
||||
cpp_args : test_cpp_args + extra_args.get('cpp_args', []),
|
||||
link_args : extra_args.get('link_args', []),
|
||||
dependencies : test_deps + extra_args.get('dependencies', []),
|
||||
install_dir: installed_tests_execdir,
|
||||
|
@ -15,8 +15,19 @@ if have_cxx
|
||||
gmodule_tests += {
|
||||
'cxx' : {
|
||||
'source' : ['cxx.cpp'],
|
||||
'suite' : ['cpp'],
|
||||
}
|
||||
}
|
||||
|
||||
foreach std, arg: cxx_standards
|
||||
gmodule_tests += {
|
||||
'cxx-@0@'.format(std) : {
|
||||
'source' : ['cxx.cpp'],
|
||||
'suite' : ['cpp'],
|
||||
'cpp_args' : [arg],
|
||||
},
|
||||
}
|
||||
endforeach
|
||||
endif
|
||||
|
||||
module_suffix = []
|
||||
@ -51,6 +62,7 @@ test_env.set('MALLOC_CHECK_', '2')
|
||||
|
||||
test_deps = [libm, thread_dep, libglib_dep, libgmodule_dep]
|
||||
test_cargs = ['-DG_LOG_DOMAIN="GModule"', '-UG_DISABLE_ASSERT']
|
||||
test_cpp_args = test_cargs
|
||||
|
||||
foreach test_name, extra_args : gmodule_tests
|
||||
source = extra_args.get('source', test_name + '.c')
|
||||
@ -72,6 +84,7 @@ foreach test_name, extra_args : gmodule_tests
|
||||
|
||||
exe = executable(test_name, source,
|
||||
c_args : test_cargs + extra_args.get('c_args', []),
|
||||
cpp_args : test_cpp_args + extra_args.get('cpp_args', []),
|
||||
link_args : extra_args.get('link_args', []),
|
||||
dependencies : test_deps + extra_args.get('dependencies', []),
|
||||
export_dynamic : extra_args.get('export_dynamic', false),
|
||||
|
@ -102,8 +102,19 @@ if have_cxx
|
||||
gobject_tests += {
|
||||
'cxx' : {
|
||||
'source' : ['cxx.cpp'],
|
||||
'suite' : ['cpp'],
|
||||
},
|
||||
}
|
||||
|
||||
foreach std, arg: cxx_standards
|
||||
gobject_tests += {
|
||||
'cxx-@0@'.format(std) : {
|
||||
'source' : ['cxx.cpp'],
|
||||
'suite' : ['cpp'],
|
||||
'cpp_args' : [arg],
|
||||
},
|
||||
}
|
||||
endforeach
|
||||
endif
|
||||
|
||||
if cc.get_id() != 'msvc'
|
||||
@ -125,6 +136,7 @@ test_env.set('MALLOC_CHECK_', '2')
|
||||
|
||||
test_deps = [libm, thread_dep, libglib_dep, libgobject_dep]
|
||||
test_cargs = ['-DG_LOG_DOMAIN="GLib-GObject"', '-UG_DISABLE_ASSERT']
|
||||
test_cpp_args = test_cargs
|
||||
|
||||
foreach test_name, extra_args : gobject_tests
|
||||
source = extra_args.get('source', test_name + '.c')
|
||||
@ -146,6 +158,7 @@ foreach test_name, extra_args : gobject_tests
|
||||
|
||||
exe = executable(test_name, source,
|
||||
c_args : test_cargs + extra_args.get('c_args', []),
|
||||
cpp_args : test_cpp_args + extra_args.get('cpp_args', []),
|
||||
dependencies : test_deps + extra_args.get('dependencies', []),
|
||||
install_dir: installed_tests_execdir,
|
||||
install_tag: 'tests',
|
||||
|
@ -13,6 +13,14 @@ cc = meson.get_compiler('c')
|
||||
have_cxx = add_languages('cpp', native: false, required: get_option('oss_fuzz').enabled())
|
||||
if have_cxx
|
||||
cxx = meson.get_compiler('cpp')
|
||||
cxx_standards = {}
|
||||
|
||||
foreach std : ['98', '03', '11', '14', '17', '20', '2b', 'latest']
|
||||
arg = (cxx.get_id() == 'msvc' ? '/std:' : '-std=') + 'c++' + std
|
||||
if cxx.has_argument(arg)
|
||||
cxx_standards += { std: arg }
|
||||
endif
|
||||
endforeach
|
||||
endif
|
||||
|
||||
cc_can_run = meson.can_run_host_binaries()
|
||||
|
Loading…
Reference in New Issue
Block a user