summaryrefslogtreecommitdiff
path: root/dev-libs/glib/files/glib-2.76.0-g_strdup-c++.patch
diff options
context:
space:
mode:
Diffstat (limited to 'dev-libs/glib/files/glib-2.76.0-g_strdup-c++.patch')
-rw-r--r--dev-libs/glib/files/glib-2.76.0-g_strdup-c++.patch132
1 files changed, 132 insertions, 0 deletions
diff --git a/dev-libs/glib/files/glib-2.76.0-g_strdup-c++.patch b/dev-libs/glib/files/glib-2.76.0-g_strdup-c++.patch
new file mode 100644
index 000000000000..23b0a1b641c1
--- /dev/null
+++ b/dev-libs/glib/files/glib-2.76.0-g_strdup-c++.patch
@@ -0,0 +1,132 @@
+https://bugs.gentoo.org/901035
+https://gitlab.gnome.org/GNOME/glib/-/merge_requests/3322
+https://gitlab.gnome.org/GNOME/glib/-/commit/cc7f2f81cc59751fcc689731dcd60af5da5723ba
+
+From cc7f2f81cc59751fcc689731dcd60af5da5723ba Mon Sep 17 00:00:00 2001
+From: Xi Ruoyao <xry111@xry111.site>
+Date: Mon, 13 Mar 2023 16:23:37 +0800
+Subject: [PATCH] gstrfuncs: Improve inline version of g_strdup() to avoid
+ breaking C++ code
+
+Wrap the logic into a G_ALWAYS_INLINE function, instead of using a
+complex statement-expression which is not allowed in braced initializer
+lists and expanded into some bad thing when it's used as
+`::g_strdup(...)`.
+
+We cannot use `__builtin_constant_p (str)` because GCC documentation
+clearly states that it always produces 0 when str is a const char *
+argument of an inline function. But `__builtin_constant_p (!str)`,
+`__builtin_constant_p (!!str)`, and
+`__builtin_constant_p (strlen (str))` functions properly with `-O1` or
+above enabled.
+
+Fixes #2936.
+--- a/glib/gstrfuncs.h
++++ b/glib/gstrfuncs.h
+@@ -204,23 +204,6 @@ gboolean (g_str_has_prefix) (const gchar *str,
+ (g_str_has_suffix) (STR, SUFFIX) \
+ )
+
+-#define g_strdup(STR) \
+- (__builtin_constant_p ((STR)) ? \
+- (G_LIKELY ((STR) != NULL) ? \
+- G_GNUC_EXTENSION ({ \
+- const char *const ___str = ((STR)); \
+- const char *const __str = _G_STR_NONNULL (___str); \
+- const size_t __str_len = strlen (__str) + 1; \
+- char *__dup_str = (char *) g_malloc (__str_len); \
+- (char *) memcpy (__dup_str, __str, __str_len); \
+- }) \
+- : \
+- (char *) (NULL) \
+- ) \
+- : \
+- (g_strdup) ((STR)) \
+- )
+-
+ #endif /* !defined (__GI_SCANNER__) */
+ #endif /* !defined (__GTK_DOC_IGNORE__) */
+ #endif /* G_GNUC_CHECK_VERSION (2, 0) */
+@@ -318,6 +301,32 @@ GLIB_AVAILABLE_IN_ALL
+ gchar* g_strjoin (const gchar *separator,
+ ...) G_GNUC_MALLOC G_GNUC_NULL_TERMINATED;
+
++#if G_GNUC_CHECK_VERSION(2, 0)
++#ifndef __GTK_DOC_IGNORE__
++#ifndef __GI_SCANNER__
++
++G_ALWAYS_INLINE static inline char *
++g_strdup_inline (const char *str)
++{
++ if (__builtin_constant_p (!str) && !str)
++ return NULL;
++
++ if (__builtin_constant_p (!!str) && !!str && __builtin_constant_p (strlen (str)))
++ {
++ const size_t len = strlen (str) + 1;
++ char *dup_str = (char *) g_malloc (len);
++ return (char *) memcpy (dup_str, str, len);
++ }
++
++ return g_strdup (str);
++}
++
++#define g_strdup(x) g_strdup_inline (x)
++
++#endif /* !defined (__GI_SCANNER__) */
++#endif /* !defined (__GTK_DOC_IGNORE__) */
++#endif /* G_GNUC_CHECK_VERSION (2, 0) */
++
+ /* Make a copy of a string interpreting C string -style escape
+ * sequences. Inverse of g_strescape. The recognized sequences are \b
+ * \f \n \r \t \\ \" and the octal format.
+--- a/glib/tests/cxx.cpp
++++ b/glib/tests/cxx.cpp
+@@ -349,6 +349,36 @@ test_strdup_macro (void)
+ g_free (str);
+ }
+
++static void
++test_strdup_macro_qualified (void)
++{
++ gchar *str;
++
++ g_assert_null (::g_strdup (NULL));
++
++ str = ::g_strdup ("C++ is cool too!");
++ g_assert_nonnull (str);
++ g_assert_cmpstr (str, ==, "C++ is cool too!");
++ g_free (str);
++}
++
++static void
++test_strdup_macro_nested_initializer (void)
++{
++ struct
++ {
++ char *p, *q;
++ } strings = {
++ g_strdup (NULL),
++ g_strdup ("C++ is cool too!"),
++ };
++
++ g_assert_null (strings.p);
++ g_assert_nonnull (strings.q);
++ g_assert_cmpstr (strings.q, ==, "C++ is cool too!");
++ g_free (strings.q);
++}
++
+ static void
+ test_str_has_prefix (void)
+ {
+@@ -527,6 +557,8 @@ main (int argc, char *argv[])
+ g_test_add_func ("/C++/str-equal", test_str_equal);
+ g_test_add_func ("/C++/strdup", test_strdup);
+ g_test_add_func ("/C++/strdup/macro", test_strdup_macro);
++ g_test_add_func ("/C++/strdup/macro/qualified", test_strdup_macro_qualified);
++ g_test_add_func ("/C++/strdup/macro/nested-initializer", test_strdup_macro_nested_initializer);
+ g_test_add_func ("/C++/str-has-prefix", test_str_has_prefix);
+ g_test_add_func ("/C++/str-has-prefix/macro", test_str_has_prefix_macro);
+ g_test_add_func ("/C++/str-has-suffix", test_str_has_suffix);
+--
+GitLab