[glib] gmessages: Fix -Wformat warnings for g_message() and friends
- From: Philip Withnall <pwithnall src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] gmessages: Fix -Wformat warnings for g_message() and friends
- Date: Fri, 2 Feb 2018 09:11:01 +0000 (UTC)
commit 32cc60dbffedc537ee2d37b9de695693e7795aae
Author: Philip Withnall <withnall endlessm com>
Date: Thu Feb 1 13:44:08 2018 +0000
gmessages: Fix -Wformat warnings for g_message() and friends
When compiling with G_LOG_USE_STRUCTURED, g_message(), g_debug(), etc.
use g_log_structured(). The message format string and its format
arguments are passed as the final set of arguments in a longer varargs
list, which includes the log domain and level (and other) fields.
Passing the message format in this way means it’s not possible for the
compiler to know to check its format placeholders when compiling with
-Wformat.
Fix support for this by adding a new semi-private helper function,
_g_log_structured_standard(), which only uses varargs for the message
format and its arguments, and uses fixed arguments for the other fields.
This is then converted to a set of GLogFields and passed to
g_log_structured() as normal.
Support for -Wformat when compiling *without* G_LOG_USE_STRUCTURED was
never broken.
Signed-off-by: Philip Withnall <withnall endlessm com>
https://bugzilla.gnome.org/show_bug.cgi?id=793074
glib/gmessages.c | 53 +++++++++++++++++++++++++++
glib/gmessages.h | 104 +++++++++++++++++++++++-------------------------------
2 files changed, 97 insertions(+), 60 deletions(-)
---
diff --git a/glib/gmessages.c b/glib/gmessages.c
index dfae4df..8833ff1 100644
--- a/glib/gmessages.c
+++ b/glib/gmessages.c
@@ -1976,6 +1976,59 @@ g_log_structured_array (GLogLevelFlags log_level,
_g_log_abort (!(log_level & G_LOG_FLAG_RECURSION));
}
+/* Semi-private helper function to implement the g_message() (etc.) macros
+ * with support for G_GNUC_PRINTF so that @message_format can be checked
+ * with -Wformat. */
+void
+g_log_structured_standard (const gchar *log_domain,
+ GLogLevelFlags log_level,
+ const gchar *file,
+ const gchar *line,
+ const gchar *func,
+ const gchar *message_format,
+ ...)
+{
+ GLogField fields[] =
+ {
+ { "PRIORITY", log_level_to_priority (log_level), -1 },
+ { "CODE_FILE", file, -1 },
+ { "CODE_LINE", line, -1 },
+ { "CODE_FUNC", func, -1 },
+ /* Filled in later: */
+ { "MESSAGE", NULL, -1 },
+ /* If @log_domain is %NULL, we will not pass this field: */
+ { "GLIB_DOMAIN", log_domain, -1 },
+ };
+ gsize n_fields;
+ gchar *message_allocated = NULL;
+ gchar buffer[1025];
+ va_list args;
+
+ va_start (args, message_format);
+
+ if (log_level & G_LOG_FLAG_RECURSION)
+ {
+ /* we use a stack buffer of fixed size, since we're likely
+ * in an out-of-memory situation
+ */
+ gsize size G_GNUC_UNUSED;
+
+ size = _g_vsnprintf (buffer, sizeof (buffer), message_format, args);
+ fields[4].value = buffer;
+ }
+ else
+ {
+ fields[4].value = message_allocated = g_strdup_vprintf (message_format, args);
+ }
+
+ va_end (args);
+
+ n_fields = G_N_ELEMENTS (fields) - ((log_domain == NULL) ? 1 : 0);
+ g_log_structured_array (log_level, fields, n_fields);
+
+ g_free (message_allocated);
+}
+
/**
* g_log_set_writer_func:
* @func: log writer function, which must not be %NULL
diff --git a/glib/gmessages.h b/glib/gmessages.h
index 1815186..cebdc16 100644
--- a/glib/gmessages.h
+++ b/glib/gmessages.h
@@ -282,6 +282,14 @@ void g_assert_warning (const char *log_domain,
const char *pretty_function,
const char *expression) G_GNUC_NORETURN;
+GLIB_AVAILABLE_IN_2_56
+void g_log_structured_standard (const gchar *log_domain,
+ GLogLevelFlags log_level,
+ const gchar *file,
+ const gchar *line,
+ const gchar *func,
+ const gchar *message_format,
+ ...) G_GNUC_PRINTF (6, 7);
#ifndef G_LOG_DOMAIN
#define G_LOG_DOMAIN ((gchar*) 0)
@@ -290,38 +298,26 @@ void g_assert_warning (const char *log_domain,
#if defined(G_HAVE_ISO_VARARGS) && !G_ANALYZER_ANALYZING
#ifdef G_LOG_USE_STRUCTURED
#define g_error(...) G_STMT_START { \
- g_log_structured (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, \
- "CODE_FILE", __FILE__, \
- "CODE_LINE", G_STRINGIFY (__LINE__), \
- "CODE_FUNC", G_STRFUNC, \
- "MESSAGE", __VA_ARGS__); \
+ g_log_structured_standard (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, \
+ __FILE__, G_STRINGIFY (__LINE__), \
+ G_STRFUNC, __VA_ARGS__); \
for (;;) ; \
} G_STMT_END
-#define g_message(...) g_log_structured (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, \
- "CODE_FILE", __FILE__, \
- "CODE_LINE", G_STRINGIFY (__LINE__), \
- "CODE_FUNC", G_STRFUNC, \
- "MESSAGE", __VA_ARGS__)
-#define g_critical(...) g_log_structured (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, \
- "CODE_FILE", __FILE__, \
- "CODE_LINE", G_STRINGIFY (__LINE__), \
- "CODE_FUNC", G_STRFUNC, \
- "MESSAGE", __VA_ARGS__)
-#define g_warning(...) g_log_structured (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, \
- "CODE_FILE", __FILE__, \
- "CODE_LINE", G_STRINGIFY (__LINE__), \
- "CODE_FUNC", G_STRFUNC, \
- "MESSAGE", __VA_ARGS__)
-#define g_info(...) g_log_structured (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, \
- "CODE_FILE", __FILE__, \
- "CODE_LINE", G_STRINGIFY (__LINE__), \
- "CODE_FUNC", G_STRFUNC, \
- "MESSAGE", __VA_ARGS__)
-#define g_debug(...) g_log_structured (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, \
- "CODE_FILE", __FILE__, \
- "CODE_LINE", G_STRINGIFY (__LINE__), \
- "CODE_FUNC", G_STRFUNC, \
- "MESSAGE", __VA_ARGS__)
+#define g_message(...) g_log_structured_standard (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, \
+ __FILE__, G_STRINGIFY (__LINE__), \
+ G_STRFUNC, __VA_ARGS__)
+#define g_critical(...) g_log_structured_standard (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, \
+ __FILE__, G_STRINGIFY (__LINE__), \
+ G_STRFUNC, __VA_ARGS__)
+#define g_warning(...) g_log_structured_standard (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, \
+ __FILE__, G_STRINGIFY (__LINE__), \
+ G_STRFUNC, __VA_ARGS__)
+#define g_info(...) g_log_structured_standard (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, \
+ __FILE__, G_STRINGIFY (__LINE__), \
+ G_STRFUNC, __VA_ARGS__)
+#define g_debug(...) g_log_structured_standard (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, \
+ __FILE__, G_STRINGIFY (__LINE__), \
+ G_STRFUNC, __VA_ARGS__)
#else
/* for(;;) ; so that GCC knows that control doesn't go past g_error().
* Put space before ending semicolon to avoid C++ build warnings.
@@ -351,38 +347,26 @@ void g_assert_warning (const char *log_domain,
#elif defined(G_HAVE_GNUC_VARARGS) && !G_ANALYZER_ANALYZING
#ifdef G_LOG_USE_STRUCTURED
#define g_error(format...) G_STMT_START { \
- g_log_structured (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, \
- "CODE_FILE", __FILE__, \
- "CODE_LINE", G_STRINGIFY (__LINE__), \
- "CODE_FUNC", G_STRFUNC, \
- "MESSAGE", format); \
+ g_log_structured_standard (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, \
+ __FILE__, G_STRINGIFY (__LINE__), \
+ G_STRFUNC, format); \
for (;;) ; \
} G_STMT_END
-#define g_message(format...) g_log_structured (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, \
- "CODE_FILE", __FILE__, \
- "CODE_LINE", G_STRINGIFY (__LINE__), \
- "CODE_FUNC", G_STRFUNC, \
- "MESSAGE", format)
-#define g_critical(format...) g_log_structured (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, \
- "CODE_FILE", __FILE__, \
- "CODE_LINE", G_STRINGIFY (__LINE__), \
- "CODE_FUNC", G_STRFUNC, \
- "MESSAGE", format)
-#define g_warning(format...) g_log_structured (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, \
- "CODE_FILE", __FILE__, \
- "CODE_LINE", G_STRINGIFY (__LINE__), \
- "CODE_FUNC", G_STRFUNC, \
- "MESSAGE", format)
-#define g_info(format...) g_log_structured (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, \
- "CODE_FILE", __FILE__, \
- "CODE_LINE", G_STRINGIFY (__LINE__), \
- "CODE_FUNC", G_STRFUNC, \
- "MESSAGE", format)
-#define g_debug(format...) g_log_structured (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, \
- "CODE_FILE", __FILE__, \
- "CODE_LINE", G_STRINGIFY (__LINE__), \
- "CODE_FUNC", G_STRFUNC, \
- "MESSAGE", format)
+#define g_message(format...) g_log_structured_standard (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, \
+ __FILE__, G_STRINGIFY (__LINE__), \
+ G_STRFUNC, format)
+#define g_critical(format...) g_log_structured_standard (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, \
+ __FILE__, G_STRINGIFY (__LINE__), \
+ G_STRFUNC, format)
+#define g_warning(format...) g_log_structured_standard (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, \
+ __FILE__, G_STRINGIFY (__LINE__), \
+ G_STRFUNC, format)
+#define g_info(format...) g_log_structured_standard (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, \
+ __FILE__, G_STRINGIFY (__LINE__), \
+ G_STRFUNC, format)
+#define g_debug(format...) g_log_structured_standard (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, \
+ __FILE__, G_STRINGIFY (__LINE__), \
+ G_STRFUNC, format)
#else
#define g_error(format...) G_STMT_START { \
g_log (G_LOG_DOMAIN, \
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]