mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-10 11:26:16 +01:00
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
This commit is contained in:
parent
07f75f6cc2
commit
32cc60dbff
@ -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
|
||||
|
104
glib/gmessages.h
104
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, \
|
||||
|
Loading…
Reference in New Issue
Block a user