diff --git a/glib/gstrfuncs.h b/glib/gstrfuncs.h index 8a6830294..cb021b658 100644 --- 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. diff --git a/glib/tests/cxx.cpp b/glib/tests/cxx.cpp index 243134009..bc7967cce 100644 --- 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);