[glib/c-cxx-std-versions: 6/7] macros: Add a generic way to get and check the supported C standard
- From: Marco Trevisan <marcotrevi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/c-cxx-std-versions: 6/7] macros: Add a generic way to get and check the supported C standard
- Date: Thu, 20 Oct 2022 14:05:32 +0000 (UTC)
commit 6ce4984fdd6bc24dc5149cb3f6bec36d4f6b3cf1
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date: Wed Sep 14 04:16:56 2022 +0200
macros: Add a generic way to get and check the supported C standard
Try to get the value of __STDC_VERSION__ if supported, if not just
fallback to the oldest standard that any compiler should handle.
docs/reference/glib/glib-sections.txt.in | 2 +
glib/docs.c | 45 +++++++++++++++++-
glib/gmacros.h | 18 ++++++++
glib/tests/cxx.cpp | 5 ++
glib/tests/macros.c | 79 ++++++++++++++++++++++++++++++++
glib/tests/meson.build | 5 +-
6 files changed, 152 insertions(+), 2 deletions(-)
---
diff --git a/docs/reference/glib/glib-sections.txt.in b/docs/reference/glib/glib-sections.txt.in
index 144e7077b0..96a432b5f4 100644
--- a/docs/reference/glib/glib-sections.txt.in
+++ b/docs/reference/glib/glib-sections.txt.in
@@ -412,6 +412,8 @@ G_GNUC_INTERNAL
G_GNUC_MAY_ALIAS
<SUBSECTION>
+G_C_STD_VERSION
+G_C_STD_CHECK_VERSION
G_CXX_STD_VERSION
G_CXX_STD_CHECK_VERSION
diff --git a/glib/docs.c b/glib/docs.c
index a96e067fbe..2453016289 100644
--- a/glib/docs.c
+++ b/glib/docs.c
@@ -2167,6 +2167,47 @@
* Since: 2.6
*/
+/**
+ * G_C_STD_VERSION:
+ *
+ * The C standard version the code is compiling against, it's normally
+ * defined with the same value of `__STDC_VERSION__` for C standard
+ * compatible compilers, while it uses the lowest standard version
+ * in pure MSVC, given that in such compiler the definition depends on
+ * a compilation flag.
+ *
+ * This is granted to be undefined when compiling with a C++ compiler.
+ *
+ * See also: %G_C_STD_CHECK_VERSION and %G_CXX_STD_VERSION
+ *
+ * Since: 2.76
+ */
+
+/**
+ * G_C_STD_CHECK_VERSION:
+ * @version: The C version to be checked for compatibility
+ *
+ * Macro to check if the current compiler supports a specified @version
+ * of the C standard. Such value must be numeric and can be provided both
+ * in the short form for the well-known versions (e.g. `90`, `99`...) or in
+ * the complete form otherwise (e.g. `199000L`, `199901L`, `205503L`...).
+ *
+ * When a C++ compiler is used, the macro is defined and returns always %FALSE.
+ *
+ * This value is compared against %G_C_STD_VERSION.
+ *
+ * |[<!-- language="C" -->
+ * #if G_C_STD_CHECK_VERSION(17)
+ * #endif
+ * ]|
+ *
+ * See also: %G_CXX_STD_CHECK_VERSION
+ *
+ * Returns: %TRUE if @version is supported by the compiler, %FALSE otherwise
+ *
+ * Since: 2.76
+ */
+
/**
* G_CXX_STD_VERSION:
*
@@ -2177,7 +2218,7 @@
*
* This is granted to be undefined when not compiling with a C++ compiler.
*
- * See also: %G_CXX_STD_CHECK_VERSION
+ * See also: %G_CXX_STD_CHECK_VERSION and %G_C_STD_VERSION
*
* Since: 2.76
*/
@@ -2200,6 +2241,8 @@
* #endif
* ]|
*
+ * See also: %G_C_STD_CHECK_VERSION
+ *
* Returns: %TRUE if @version is supported by the compiler, %FALSE otherwise
*
* Since: 2.76
diff --git a/glib/gmacros.h b/glib/gmacros.h
index 4c9ffbc4c6..a110f42db2 100644
--- a/glib/gmacros.h
+++ b/glib/gmacros.h
@@ -69,8 +69,26 @@
# undef G_CXX_STD_VERSION
# define G_CXX_STD_CHECK_VERSION(version) (0)
+# if defined (__STDC_VERSION__)
+# define G_C_STD_VERSION __STDC_VERSION__
+# else
+# define G_C_STD_VERSION 199000L
+# endif /* defined (__STDC_VERSION__) */
+
+# define G_C_STD_CHECK_VERSION(version) ( \
+ ((version) >= 199000L && (version) <= G_C_STD_VERSION) || \
+ ((version) == 89 && G_C_STD_VERSION >= 199000L) || \
+ ((version) == 90 && G_C_STD_VERSION >= 199000L) || \
+ ((version) == 99 && G_C_STD_VERSION >= 199901L) || \
+ ((version) == 11 && G_C_STD_VERSION >= 201112L) || \
+ ((version) == 17 && G_C_STD_VERSION >= 201710L) || \
+ 0)
+
#else /* defined (__cplusplus) */
+# undef G_C_STD_VERSION
+# define G_C_STD_CHECK_VERSION(version) (0)
+
# if defined (_MSVC_LANG)
# define G_CXX_STD_VERSION (_MSVC_LANG > __cplusplus ? _MSVC_LANG : __cplusplus)
# else
diff --git a/glib/tests/cxx.cpp b/glib/tests/cxx.cpp
index 5d9d537a5a..ce354d1a6b 100644
--- a/glib/tests/cxx.cpp
+++ b/glib/tests/cxx.cpp
@@ -23,7 +23,12 @@
#error G_CXX_STD_VERSION is not defined
#endif
+#ifdef G_C_STD_VERSION
+#error G_C_STD_VERSION should be undefined in C programs
+#endif
+
G_STATIC_ASSERT (G_CXX_STD_VERSION);
+G_STATIC_ASSERT (!G_C_STD_CHECK_VERSION (99));
#if G_CXX_STD_VERSION >= 199711L
G_STATIC_ASSERT (G_CXX_STD_CHECK_VERSION (98));
diff --git a/glib/tests/macros.c b/glib/tests/macros.c
index b18f3a3a6d..8eb6fbca1c 100644
--- a/glib/tests/macros.c
+++ b/glib/tests/macros.c
@@ -38,6 +38,81 @@
#endif
G_STATIC_ASSERT (!G_CXX_STD_CHECK_VERSION (98));
+G_STATIC_ASSERT (G_C_STD_CHECK_VERSION (89));
+G_STATIC_ASSERT (G_C_STD_CHECK_VERSION (90));
+
+#if G_C_STD_VERSION >= 199000L
+ G_STATIC_ASSERT (G_C_STD_CHECK_VERSION (89));
+ G_STATIC_ASSERT (G_C_STD_CHECK_VERSION (90));
+ G_STATIC_ASSERT (G_C_STD_CHECK_VERSION (199000L));
+#endif
+
+#if G_C_STD_VERSION == 198900L
+ G_STATIC_ASSERT (!G_C_STD_CHECK_VERSION (99));
+ G_STATIC_ASSERT (!G_C_STD_CHECK_VERSION (199901L));
+ G_STATIC_ASSERT (!G_C_STD_CHECK_VERSION (11));
+ G_STATIC_ASSERT (!G_C_STD_CHECK_VERSION (201112L));
+ G_STATIC_ASSERT (!G_C_STD_CHECK_VERSION (17));
+ G_STATIC_ASSERT (!G_C_STD_CHECK_VERSION (201710L));
+#endif
+
+#if G_C_STD_VERSION >= 199901L
+ G_STATIC_ASSERT (G_C_STD_CHECK_VERSION (99));
+ G_STATIC_ASSERT (G_C_STD_CHECK_VERSION (199901L));
+#endif
+
+#if G_C_STD_VERSION == 199901L
+ G_STATIC_ASSERT (!G_C_STD_CHECK_VERSION (11));
+ G_STATIC_ASSERT (!G_C_STD_CHECK_VERSION (201112L));
+ G_STATIC_ASSERT (!G_C_STD_CHECK_VERSION (17));
+ G_STATIC_ASSERT (!G_C_STD_CHECK_VERSION (201710L));
+#endif
+
+#if G_C_STD_VERSION >= 201112L
+ G_STATIC_ASSERT (G_C_STD_CHECK_VERSION (11));
+ G_STATIC_ASSERT (G_C_STD_CHECK_VERSION (201112L));
+#endif
+
+#if G_C_STD_VERSION == 201112L
+ G_STATIC_ASSERT (!G_C_STD_CHECK_VERSION (17));
+ G_STATIC_ASSERT (!G_C_STD_CHECK_VERSION (201710L));
+#endif
+
+#if G_C_STD_VERSION >= 201710L
+ G_STATIC_ASSERT (G_C_STD_CHECK_VERSION (17));
+ G_STATIC_ASSERT (G_C_STD_CHECK_VERSION (201710L));
+#endif
+
+#if G_C_STD_VERSION == 201710L
+ G_STATIC_ASSERT (!G_C_STD_CHECK_VERSION (23));
+ G_STATIC_ASSERT (!G_C_STD_CHECK_VERSION (202300L));
+#endif
+
+#ifdef _G_EXPECTED_C_STANDARD
+static void
+test_c_standard (void)
+{
+ guint64 std_version = 0;
+
+ if (!g_ascii_string_to_unsigned (_G_EXPECTED_C_STANDARD, 10, 0, G_MAXUINT64,
+ &std_version, NULL))
+ {
+ g_test_skip ("Expected standard value is non-numeric: "
+ _G_EXPECTED_C_STANDARD);
+ return;
+ }
+
+ g_assert_true (G_C_STD_CHECK_VERSION (std_version));
+
+ if (std_version > 80 && std_version < 99)
+ std_version = 90;
+
+ if (std_version >= 90)
+ g_assert_cmpuint (G_C_STD_VERSION, >=, (std_version + 1900) * 100);
+ else
+ g_assert_cmpuint (G_C_STD_VERSION, >=, (std_version + 2000) * 100);
+}
+#endif
/* Test that G_STATIC_ASSERT_EXPR can be used as an expression */
static void
@@ -82,6 +157,10 @@ main (int argc,
{
g_test_init (&argc, &argv, NULL);
+#ifdef _G_EXPECTED_C_STANDARD
+ g_test_add_func ("/C/standard-" _G_EXPECTED_C_STANDARD, test_c_standard);
+#endif
+
g_test_add_func ("/alignof/fallback", test_alignof_fallback);
g_test_add_func ("/assert/static", test_assert_static);
g_test_add_func ("/struct/sizeof_member", test_struct_sizeof_member);
diff --git a/glib/tests/meson.build b/glib/tests/meson.build
index 5108944c19..f9f47cf917 100644
--- a/glib/tests/meson.build
+++ b/glib/tests/meson.build
@@ -270,7 +270,10 @@ foreach test_name, extra_args : glib_tests
'@0@-c-@1@'.format(test_name, std) : extra_args + {
'source' : extra_args.get('source', test_name + '.c'),
'suite' : ['cc'] + extra_args.get('suite', []),
- 'c_args' : [c_standards.get(std)] + extra_args.get('c_args', []),
+ 'c_args' : [
+ c_standards.get(std),
+ '-D_G_EXPECTED_C_STANDARD="@0@"'.format(std)
+ ] + extra_args.get('c_args', []),
}
}
endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]