mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-10 11:26:16 +01:00
string: Make g_string_free (_, FALSE) warn on unused result
...much like g_string_free_and_steal () does; by redirecting g_string_free (_, FALSE) calls (when we can detect them) to g_string_free_and_steal (). This relies on some unpretty macros, but should be entirely transparent to any users of g_string_free (). In particular, the macro only evaluates its arguments once, no matter which branch ends up being taken. The ternary operator the macro expands to always gets optimized out, even at -O0: there is only one call to either g_string_free () or g_string_free_and_steal () in the compiled code, with no run-time branching. Add a test for ensuring this works as expected in C++ too. Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
This commit is contained in:
parent
bccff754b6
commit
c3d07a625a
@ -206,8 +206,8 @@ g_string_new_len (const gchar *init,
|
||||
* (i.e. %NULL if @free_segment is %TRUE)
|
||||
*/
|
||||
gchar *
|
||||
g_string_free (GString *string,
|
||||
gboolean free_segment)
|
||||
(g_string_free) (GString *string,
|
||||
gboolean free_segment)
|
||||
{
|
||||
gchar *segment;
|
||||
|
||||
@ -242,7 +242,7 @@ g_string_free (GString *string,
|
||||
gchar *
|
||||
g_string_free_and_steal (GString *string)
|
||||
{
|
||||
return g_string_free (string, FALSE);
|
||||
return (g_string_free) (string, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -57,10 +57,23 @@ GString* g_string_new_len (const gchar *init,
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
GString* g_string_sized_new (gsize dfl_size);
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
gchar* g_string_free (GString *string,
|
||||
gchar* (g_string_free) (GString *string,
|
||||
gboolean free_segment);
|
||||
GLIB_AVAILABLE_IN_2_76
|
||||
gchar* g_string_free_and_steal (GString *string) G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
#if G_GNUC_CHECK_VERSION (2, 0) && (GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_76)
|
||||
|
||||
#define g_string_free(str, free_segment) \
|
||||
(__builtin_constant_p (free_segment) ? \
|
||||
((free_segment) ? \
|
||||
(g_string_free) ((str), (free_segment)) : \
|
||||
g_string_free_and_steal (str)) \
|
||||
: \
|
||||
(g_string_free) ((str), (free_segment)))
|
||||
|
||||
#endif /* G_GNUC_CHECK_VERSION (2, 0) && (GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_76) */
|
||||
|
||||
GLIB_AVAILABLE_IN_2_34
|
||||
GBytes* g_string_free_to_bytes (GString *string);
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
|
@ -472,6 +472,35 @@ test_string_append (void)
|
||||
g_string_free (string, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
test_string_free (void)
|
||||
{
|
||||
GString *str;
|
||||
gchar *data;
|
||||
|
||||
g_test_message ("Test that g_string_free() macro compiles and doesn’t "
|
||||
"cause any compiler warnings in C++ mode");
|
||||
|
||||
/* Test that g_string_free (_, TRUE) does not cause a warning if
|
||||
* its return value is unused. */
|
||||
str = g_string_new ("test");
|
||||
g_string_free (str, TRUE);
|
||||
|
||||
/* Test that g_string_free (_, FALSE) does not emit a warning if
|
||||
* its return value is used. */
|
||||
str = g_string_new ("test");
|
||||
data = g_string_free (str, FALSE);
|
||||
g_free (data);
|
||||
|
||||
/* Test that g_string_free () with an expression that is always FALSE
|
||||
* at runtime, but the compiler can't know it, does not cause any
|
||||
* warnings if its return value is unused. */
|
||||
str = g_string_new ("test");
|
||||
data = str->str;
|
||||
g_string_free (str, g_test_get_path ()[0] == 0);
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
@ -502,6 +531,7 @@ main (int argc, char *argv[])
|
||||
g_test_add_func ("/C++/str-has-suffix", test_str_has_suffix);
|
||||
g_test_add_func ("/C++/str-has-suffix/macro", test_str_has_suffix_macro);
|
||||
g_test_add_func ("/C++/string-append", test_string_append);
|
||||
g_test_add_func ("/C++/string-free", test_string_free);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user