[glib/atomic-older-cplusplus: 7/10] gmacros: Define G_CXX_STD_VERSION and check macros
- From: Marco Trevisan <marcotrevi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/atomic-older-cplusplus: 7/10] gmacros: Define G_CXX_STD_VERSION and check macros
- Date: Wed, 14 Sep 2022 01:39:29 +0000 (UTC)
commit 0c6ca4d48907673b4a2c8ac3f23571fa9212ed1d
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date: Wed Sep 14 01:03:22 2022 +0200
gmacros: Define G_CXX_STD_VERSION and check macros
Sadly, in C++ there's not an universal way to get what language standard
is used to compile GLib-based programs, in fact while most compilers
relies on `__cplusplus`, MSVC is defining that, but it does not use it
to expose such information (unless `/Zc:__cplusplus` arg is used).
On the other side, MSVC reports the language standard via _MSVC_LANG [1].
This complication makes us defining some macros in a very complex way
(such as glib_typeof()), because we need to perform many checks just to
understand if a C++ compiler is used and what standard is expecting.
To avoid this, define multiple macros that can be used to figure out
what C++ standard is being used.
[1] https://docs.microsoft.com/en-us/cpp/build/reference/zc-cplusplus?view=msvc-170
docs/reference/glib/glib-sections.txt | 2 +
glib/gmacros.h | 22 ++++++++++
glib/tests/cxx.cpp | 75 +++++++++++++++++++++++++++++++++--
glib/tests/macros.c | 6 +++
4 files changed, 102 insertions(+), 3 deletions(-)
---
diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt
index 38b35386e3..daf53417a9 100644
--- a/docs/reference/glib/glib-sections.txt
+++ b/docs/reference/glib/glib-sections.txt
@@ -780,6 +780,8 @@ GLIB_UNAVAILABLE_STATIC_INLINE
GLIB_UNAVAILABLE_TYPE
G_ANALYZER_ANALYZING
G_ANALYZER_NORETURN
+G_CXX_STD_VERSION
+G_CXX_STD_CHECK_VERSION
g_autoptr_cleanup_generic_gfree
glib_typeof
g_macro__has_attribute
diff --git a/glib/gmacros.h b/glib/gmacros.h
index d4e5124cf1..6b9554796b 100644
--- a/glib/gmacros.h
+++ b/glib/gmacros.h
@@ -64,6 +64,28 @@
#define G_GNUC_EXTENSION
#endif
+#if defined (__cplusplus)
+
+# if defined (_MSVC_LANG)
+# define G_CXX_STD_VERSION _MSVC_LANG
+# else
+# define G_CXX_STD_VERSION __cplusplus
+# endif /* defined(_MSVC_LANG) */
+
+# define G_CXX_STD_CHECK_VERSION(v) ( \
+ ((v) >= 199711L && (v) <= G_CXX_STD_VERSION) || \
+ ((v) == 98 && G_CXX_STD_VERSION >= 199711L) || \
+ ((v) == 11 && G_CXX_STD_VERSION >= 201103L) || \
+ ((v) == 14 && G_CXX_STD_VERSION >= 201402L) || \
+ ((v) == 17 && G_CXX_STD_VERSION >= 201703L) || \
+ ((v) == 20 && G_CXX_STD_VERSION >= 202002L) || \
+ 0)
+
+#else /* !defined (__cplusplus) */
+# undef G_CXX_STD_VERSION
+# define G_CXX_STD_CHECK_VERSION(v) (0)
+#endif /* defined (__cplusplus) */
+
/* Every compiler that we target supports inlining, but some of them may
* complain about it if we don't say "__inline". If we have C99, or if
* we are using C++, then we can use "inline" directly. Unfortunately
diff --git a/glib/tests/cxx.cpp b/glib/tests/cxx.cpp
index 6ac60791c8..fcdd858e46 100644
--- a/glib/tests/cxx.cpp
+++ b/glib/tests/cxx.cpp
@@ -19,6 +19,75 @@
#include <glib.h>
+#if !defined (G_CXX_STD_VERSION) || !defined (G_CXX_STD_CHECK_VERSION)
+#error G_CXX_STD_VERSION is not defined
+#endif
+
+G_STATIC_ASSERT (G_CXX_STD_VERSION);
+
+#if G_CXX_STD_VERSION >= 199711L
+ G_STATIC_ASSERT (G_CXX_STD_CHECK_VERSION (98));
+ G_STATIC_ASSERT (G_CXX_STD_CHECK_VERSION (199711L));
+#endif
+
+#if G_CXX_STD_VERSION == 199711L
+ G_STATIC_ASSERT (!G_CXX_STD_CHECK_VERSION (11));
+ G_STATIC_ASSERT (!G_CXX_STD_CHECK_VERSION (201103L));
+ G_STATIC_ASSERT (!G_CXX_STD_CHECK_VERSION (14));
+ G_STATIC_ASSERT (!G_CXX_STD_CHECK_VERSION (201402L));
+ G_STATIC_ASSERT (!G_CXX_STD_CHECK_VERSION (17));
+ G_STATIC_ASSERT (!G_CXX_STD_CHECK_VERSION (201703L));
+ G_STATIC_ASSERT (!G_CXX_STD_CHECK_VERSION (20));
+ G_STATIC_ASSERT (!G_CXX_STD_CHECK_VERSION (202002L));
+#endif
+
+#if G_CXX_STD_VERSION >= 201103L
+ G_STATIC_ASSERT (G_CXX_STD_CHECK_VERSION (11));
+ G_STATIC_ASSERT (G_CXX_STD_CHECK_VERSION (201103L));
+#endif
+
+#if G_CXX_STD_VERSION == 201103L
+ G_STATIC_ASSERT (!G_CXX_STD_CHECK_VERSION (14));
+ G_STATIC_ASSERT (!G_CXX_STD_CHECK_VERSION (201402L));
+ G_STATIC_ASSERT (!G_CXX_STD_CHECK_VERSION (17));
+ G_STATIC_ASSERT (!G_CXX_STD_CHECK_VERSION (201703L));
+ G_STATIC_ASSERT (!G_CXX_STD_CHECK_VERSION (20));
+ G_STATIC_ASSERT (!G_CXX_STD_CHECK_VERSION (202002L));
+#endif
+
+#if G_CXX_STD_VERSION >= 201402L
+ G_STATIC_ASSERT (G_CXX_STD_CHECK_VERSION (14));
+ G_STATIC_ASSERT (G_CXX_STD_CHECK_VERSION (201402L));
+#endif
+
+#if G_CXX_STD_VERSION == 201402L
+ G_STATIC_ASSERT (!G_CXX_STD_CHECK_VERSION (17));
+ G_STATIC_ASSERT (!G_CXX_STD_CHECK_VERSION (201703L));
+ G_STATIC_ASSERT (!G_CXX_STD_CHECK_VERSION (20));
+ G_STATIC_ASSERT (!G_CXX_STD_CHECK_VERSION (202002L));
+#endif
+
+#if G_CXX_STD_VERSION >= 201703L
+ G_STATIC_ASSERT (G_CXX_STD_CHECK_VERSION (17));
+ G_STATIC_ASSERT (G_CXX_STD_CHECK_VERSION (201703L));
+#endif
+
+#if G_CXX_STD_VERSION == 201703L
+ G_STATIC_ASSERT (!G_CXX_STD_CHECK_VERSION (20));
+ G_STATIC_ASSERT (!G_CXX_STD_CHECK_VERSION (202002L));
+#endif
+
+#if G_CXX_STD_VERSION >= 202002L
+ G_STATIC_ASSERT (G_CXX_STD_CHECK_VERSION (20));
+ G_STATIC_ASSERT (G_CXX_STD_CHECK_VERSION (202002L));
+#endif
+
+#if G_CXX_STD_VERSION == 202002L
+ G_STATIC_ASSERT (!G_CXX_STD_CHECK_VERSION (23));
+ G_STATIC_ASSERT (!G_CXX_STD_CHECK_VERSION (202300L));
+#endif
+
+
typedef struct
{
int dummy;
@@ -34,7 +103,7 @@ test_typeof (void)
MyObject *obj3 = g_atomic_pointer_get (&obj2);
g_assert_true (obj3 == obj);
-#if __cplusplus >= 201103L
+#if G_CXX_STD_CHECK_VERSION (11)
MyObject *obj4 = nullptr;
#else
MyObject *obj4 = NULL;
@@ -42,7 +111,7 @@ test_typeof (void)
g_atomic_pointer_set (&obj4, obj3);
g_assert_true (obj4 == obj);
-#if __cplusplus >= 201103L
+#if G_CXX_STD_CHECK_VERSION (11)
MyObject *obj5 = nullptr;
g_atomic_pointer_compare_and_exchange (&obj5, nullptr, obj4);
#else
@@ -195,7 +264,7 @@ test_steal_pointer (void)
int
main (int argc, char *argv[])
{
-#if __cplusplus >= 201103L
+#if G_CXX_STD_CHECK_VERSION (11)
g_test_init (&argc, &argv, nullptr);
#else
g_test_init (&argc, &argv, NULL);
diff --git a/glib/tests/macros.c b/glib/tests/macros.c
index efe632b521..38372518be 100644
--- a/glib/tests/macros.c
+++ b/glib/tests/macros.c
@@ -22,6 +22,12 @@
#include <glib.h>
+#ifdef G_CXX_STD_VERSION
+#error G_CXX_STD_VERSION should be undefined in C programs
+#endif
+
+G_STATIC_ASSERT (!G_CXX_STD_CHECK_VERSION (98));
+
/* Test that G_STATIC_ASSERT_EXPR can be used as an expression */
static void
test_assert_static (void)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]