The -Wsuggest-attribute=format warning makes the compiler suggest places
where __attribute__((format(...))) would likely be useful. This patch
turns it on and adds such attributes everywhere my compiler (GCC 9)
suggested to add them.
In cases where we re-use the same format string multiple times, like:
const char *const msg = "Hello %d\n";
BT_LOGE(msg, some_value);
BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_MESSAGE_ITERATOR("modname", msg, some_value);
... my compiler (gcc (Arch Linux 9.2.1+
20200130-2) 9.2.1
20200130)
complains that the format string is not a literal, even though the `msg`
variable is const and assigned a literal. I've replaced these with a
macro.
Change-Id: I40dd2e70649ec2b651e0109097c217ca9557ad69
Signed-off-by: Simon Marchi <simon.marchi@efficios.com>
Reviewed-on: https://review.lttng.org/c/babeltrace/+/3232
Tested-by: jenkins <jenkins@lttng.org>
Reviewed-by: Philippe Proulx <eeppeliteloop@gmail.com>
-Wredundant-decls dnl
-Wshadow dnl
-Wjump-misses-init dnl
-Wredundant-decls dnl
-Wshadow dnl
-Wjump-misses-init dnl
+ -Wsuggest-attribute=format dnl
-Wtautological-constant-out-of-range-compare dnl
-Wnested-externs dnl
-Wwrite-strings dnl
-Wtautological-constant-out-of-range-compare dnl
-Wnested-externs dnl
-Wwrite-strings dnl
# define __BT_UPCAST_CONST(_type, _p) ((const _type *) (_p))
#endif
# define __BT_UPCAST_CONST(_type, _p) ((const _type *) (_p))
#endif
+/*
+ * Internal: attribute suitable to tag functions as having printf()-like
+ * arguments.
+ *
+ * We always define `__USE_MINGW_ANSI_STDIO` when building with MinGW, so use
+ * `gnu_printf` directly rather than `__MINGW_PRINTF_FORMAT` (which would require
+ * including `stdio.h`).
+ */
+#ifdef __MINGW32__
+# define __BT_PRINTF_FORMAT gnu_printf
+#else
+# define __BT_PRINTF_FORMAT printf
+#endif
+
+#define __BT_ATTR_FORMAT_PRINTF(_string_index, _first_to_check) \
+ __attribute__((format(__BT_PRINTF_FORMAT, _string_index, _first_to_check)))
+
#include <babeltrace2/error-reporting.h>
#include <babeltrace2/graph/component-class-dev.h>
#include <babeltrace2/graph/component-class.h>
#include <babeltrace2/error-reporting.h>
#include <babeltrace2/graph/component-class-dev.h>
#include <babeltrace2/graph/component-class.h>
Calls this function with \c __FILE__ and \c __LINE__ as the
\bt_p{file_name} and \bt_p{line_number} parameters.
*/
Calls this function with \c __FILE__ and \c __LINE__ as the
\bt_p{file_name} and \bt_p{line_number} parameters.
*/
+extern __BT_ATTR_FORMAT_PRINTF(4, 5)
bt_current_thread_error_append_cause_status
bt_current_thread_error_append_cause_from_component(
bt_self_component *self_component, const char *file_name,
bt_current_thread_error_append_cause_status
bt_current_thread_error_append_cause_from_component(
bt_self_component *self_component, const char *file_name,
Calls this function with \c __FILE__ and \c __LINE__ as the
\bt_p{file_name} and \bt_p{line_number} parameters.
*/
Calls this function with \c __FILE__ and \c __LINE__ as the
\bt_p{file_name} and \bt_p{line_number} parameters.
*/
+extern __BT_ATTR_FORMAT_PRINTF(4, 5)
bt_current_thread_error_append_cause_status
bt_current_thread_error_append_cause_from_message_iterator(
bt_self_message_iterator *self_message_iterator,
bt_current_thread_error_append_cause_status
bt_current_thread_error_append_cause_from_message_iterator(
bt_self_message_iterator *self_message_iterator,
Calls this function with \c __FILE__ and \c __LINE__ as the
\bt_p{file_name} and \bt_p{line_number} parameters.
*/
Calls this function with \c __FILE__ and \c __LINE__ as the
\bt_p{file_name} and \bt_p{line_number} parameters.
*/
+extern __BT_ATTR_FORMAT_PRINTF(4, 5)
bt_current_thread_error_append_cause_status
bt_current_thread_error_append_cause_from_component_class(
bt_self_component_class *self_component_class,
bt_current_thread_error_append_cause_status
bt_current_thread_error_append_cause_from_component_class(
bt_self_component_class *self_component_class,
Calls this function with \c __FILE__ and \c __LINE__ as the
\bt_p{file_name} and \bt_p{line_number} parameters.
*/
Calls this function with \c __FILE__ and \c __LINE__ as the
\bt_p{file_name} and \bt_p{line_number} parameters.
*/
+extern __BT_ATTR_FORMAT_PRINTF(4, 5)
bt_current_thread_error_append_cause_status
bt_current_thread_error_append_cause_from_unknown(
const char *module_name, const char *file_name,
bt_current_thread_error_append_cause_status
bt_current_thread_error_append_cause_from_unknown(
const char *module_name, const char *file_name,
#define ARGPAR_ASSERT(_cond) assert(_cond)
#define ARGPAR_ASSERT(_cond) assert(_cond)
+#ifdef __MINGW_PRINTF_FORMAT
+# define ARGPAR_PRINTF_FORMAT __MINGW_PRINTF_FORMAT
+#else
+# define ARGPAR_PRINTF_FORMAT printf
+#endif
+
+static __attribute__((format(ARGPAR_PRINTF_FORMAT, 1, 0)))
char *argpar_vasprintf(const char *fmt, va_list args)
{
int len1, len2;
char *argpar_vasprintf(const char *fmt, va_list args)
{
int len1, len2;
+static __attribute__((format(ARGPAR_PRINTF_FORMAT, 1, 2)))
char *argpar_asprintf(const char *fmt, ...)
{
va_list args;
char *argpar_asprintf(const char *fmt, ...)
{
va_list args;
+static __attribute__((format(ARGPAR_PRINTF_FORMAT, 2, 3)))
bool argpar_string_append_printf(char **str, const char *fmt, ...)
{
char *new_str = NULL;
bool argpar_string_append_printf(char **str, const char *fmt, ...)
{
char *new_str = NULL;
*/
#define __BT_IN_BABELTRACE_H
*/
#define __BT_IN_BABELTRACE_H
+/*
+ * Define `__BT_ATTR_FORMAT_PRINTF` to nothing, otherwise SWIG fails to parse
+ * the included header files that use it.
+ */
+#define __BT_ATTR_FORMAT_PRINTF(_string_index, _first_to_check)
+
/* Common types */
%include <babeltrace2/types.h>
/* Common types */
%include <babeltrace2/types.h>
result = bt_value_map_create();
if (!result) {
result = bt_value_map_create();
if (!result) {
- static const char * const err = "Failed to create a map value.";
- BT_LOGE_STR(err);
- BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name, err);
+#define BT_FMT "Failed to create a map value."
+ BT_LOGE_STR(BT_FMT);
+ BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name, BT_FMT);
+#undef BT_FMT
PyErr_NoMemory();
goto end;
}
PyErr_NoMemory();
goto end;
}
* a BT component object instance.
*/
* a BT component object instance.
*/
+#define BT_FMT_SWIG_ALLOC_FAILED "Failed to create a SWIG pointer object."
+
static GHashTable *bt_cc_ptr_to_py_cls;
static
static GHashTable *bt_cc_ptr_to_py_cls;
static
SWIGTYPE_p_bt_value, 0);
if (!py_params_ptr) {
BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, log_level, self_component,
SWIGTYPE_p_bt_value, 0);
if (!py_params_ptr) {
BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, log_level, self_component,
- "Failed to create a SWIG pointer object.");
+ BT_FMT_SWIG_ALLOC_FAILED);
self_comp_cls_type_swig_type, 0);
if (!py_comp_ptr) {
BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, log_level, self_component,
self_comp_cls_type_swig_type, 0);
if (!py_comp_ptr) {
BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, log_level, self_component,
- "Failed to create a SWIG pointer object.");
+ BT_FMT_SWIG_ALLOC_FAILED);
SWIGTYPE_p_bt_value, 0);
if (!py_params_ptr) {
BT_LOG_WRITE_CUR_LVL(BT_LOG_ERROR, log_level, BT_LOG_TAG,
SWIGTYPE_p_bt_value, 0);
if (!py_params_ptr) {
BT_LOG_WRITE_CUR_LVL(BT_LOG_ERROR, log_level, BT_LOG_TAG,
- "Failed to create a SWIG pointer object.");
+ BT_FMT_SWIG_ALLOC_FAILED);
self_component_port_swig_type, 0);
if (!py_self_port_ptr) {
BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, log_level, self_component,
self_component_port_swig_type, 0);
if (!py_self_port_ptr) {
BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, log_level, self_component,
- "Failed to create a SWIG pointer object.");
+ BT_FMT_SWIG_ALLOC_FAILED);
status = __BT_FUNC_STATUS_MEMORY_ERROR;
goto end;
}
status = __BT_FUNC_STATUS_MEMORY_ERROR;
goto end;
}
other_port_swig_type, 0);
if (!py_other_port_ptr) {
BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, log_level, self_component,
other_port_swig_type, 0);
if (!py_other_port_ptr) {
BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, log_level, self_component,
- "Failed to create a SWIG pointer object.");
+ BT_FMT_SWIG_ALLOC_FAILED);
status = __BT_FUNC_STATUS_MEMORY_ERROR;
goto end;
}
status = __BT_FUNC_STATUS_MEMORY_ERROR;
goto end;
}
SWIGTYPE_p_bt_value, 0);
if (!py_params_ptr) {
BT_LOG_WRITE_CUR_LVL(BT_LOG_ERROR, log_level, BT_LOG_TAG,
SWIGTYPE_p_bt_value, 0);
if (!py_params_ptr) {
BT_LOG_WRITE_CUR_LVL(BT_LOG_ERROR, log_level, BT_LOG_TAG,
- "Failed to create a SWIG pointer object.");
+ BT_FMT_SWIG_ALLOC_FAILED);
SWIGTYPE_p_bt_private_query_executor, 0);
if (!py_priv_query_exec_ptr) {
BT_LOG_WRITE_CUR_LVL(BT_LOG_ERROR, log_level, BT_LOG_TAG,
SWIGTYPE_p_bt_private_query_executor, 0);
if (!py_priv_query_exec_ptr) {
BT_LOG_WRITE_CUR_LVL(BT_LOG_ERROR, log_level, BT_LOG_TAG,
- "Failed to create a SWIG pointer object.");
+ BT_FMT_SWIG_ALLOC_FAILED);
py_iter_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(self_message_iterator),
SWIGTYPE_p_bt_self_message_iterator, 0);
if (!py_iter_ptr) {
py_iter_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(self_message_iterator),
SWIGTYPE_p_bt_self_message_iterator, 0);
if (!py_iter_ptr) {
- const char *err = "Failed to create a SWIG pointer object.";
-
BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, log_level, self_component,
BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, log_level, self_component,
+ BT_FMT_SWIG_ALLOC_FAILED);
BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_MESSAGE_ITERATOR(
BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_MESSAGE_ITERATOR(
- self_message_iterator, err);
+ self_message_iterator, BT_FMT_SWIG_ALLOC_FAILED);
py_config_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(config),
SWIGTYPE_p_bt_self_message_iterator_configuration, 0);
if (!py_config_ptr) {
py_config_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(config),
SWIGTYPE_p_bt_self_message_iterator_configuration, 0);
if (!py_config_ptr) {
- const char *err = "Failed to create a SWIG pointer object";
-
BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, log_level, self_component,
BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, log_level, self_component,
+ BT_FMT_SWIG_ALLOC_FAILED);
BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_MESSAGE_ITERATOR(
BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_MESSAGE_ITERATOR(
- self_message_iterator, err);
+ self_message_iterator, BT_FMT_SWIG_ALLOC_FAILED);
SWIG_as_voidptr(self_component_port_output),
SWIGTYPE_p_bt_self_component_port_output, 0);
if (!py_component_port_output_ptr) {
SWIG_as_voidptr(self_component_port_output),
SWIGTYPE_p_bt_self_component_port_output, 0);
if (!py_component_port_output_ptr) {
- const char *err = "Failed to create a SWIG pointer object.";
-
BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, log_level, self_component,
BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, log_level, self_component,
+ "%s", BT_FMT_SWIG_ALLOC_FAILED);
BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_MESSAGE_ITERATOR(
BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_MESSAGE_ITERATOR(
- self_message_iterator, err);
+ self_message_iterator, BT_FMT_SWIG_ALLOC_FAILED);
* bt_g_string_append_printf cannot be inlined because it expects a
* variadic argument list.
*/
* bt_g_string_append_printf cannot be inlined because it expects a
* variadic argument list.
*/
+BT_HIDDEN __BT_ATTR_FORMAT_PRINTF(2, 3)
int bt_common_g_string_append_printf(GString *str, const char *fmt, ...);
static inline
int bt_common_g_string_append_printf(GString *str, const char *fmt, ...);
static inline
BT_HIDDEN
void bt_error_destroy(struct bt_error *error);
BT_HIDDEN
void bt_error_destroy(struct bt_error *error);
+BT_HIDDEN __BT_ATTR_FORMAT_PRINTF(5, 0)
int bt_error_append_cause_from_unknown(struct bt_error *error,
const char *module_name, const char *file_name,
uint64_t line_no, const char *msg_fmt, va_list args);
int bt_error_append_cause_from_unknown(struct bt_error *error,
const char *module_name, const char *file_name,
uint64_t line_no, const char *msg_fmt, va_list args);
+BT_HIDDEN __BT_ATTR_FORMAT_PRINTF(5, 0)
int bt_error_append_cause_from_component(
struct bt_error *error, bt_self_component *self_comp,
const char *file_name, uint64_t line_no,
const char *msg_fmt, va_list args);
int bt_error_append_cause_from_component(
struct bt_error *error, bt_self_component *self_comp,
const char *file_name, uint64_t line_no,
const char *msg_fmt, va_list args);
+BT_HIDDEN __BT_ATTR_FORMAT_PRINTF(5, 0)
int bt_error_append_cause_from_component_class(
struct bt_error *error,
bt_self_component_class *self_comp_class,
const char *file_name, uint64_t line_no,
const char *msg_fmt, va_list args);
int bt_error_append_cause_from_component_class(
struct bt_error *error,
bt_self_component_class *self_comp_class,
const char *file_name, uint64_t line_no,
const char *msg_fmt, va_list args);
+BT_HIDDEN __BT_ATTR_FORMAT_PRINTF(5, 0)
int bt_error_append_cause_from_message_iterator(
struct bt_error *error, bt_self_message_iterator *self_iter,
const char *file_name, uint64_t line_no,
int bt_error_append_cause_from_message_iterator(
struct bt_error *error, bt_self_message_iterator *self_iter,
const char *file_name, uint64_t line_no,
-static void put_msg(bt_log_message *const msg,
+static _BT_LOG_PRINTFLIKE(2, 0)
+void put_msg(bt_log_message *const msg,
const char *const fmt, va_list va)
{
int n;
const char *const fmt, va_list va)
{
int n;
_bt_log_global_output.callback = callback;
}
_bt_log_global_output.callback = callback;
}
-static void _bt_log_write_imp(
+static _BT_LOG_PRINTFLIKE(6, 0)
+void _bt_log_write_imp(
const bt_log_spec *log,
const src_location *const src, const mem_block *const mem,
const int lvl, const char *const tag, const char *const fmt, va_list va)
const bt_log_spec *log,
const src_location *const src, const mem_block *const mem,
const int lvl, const char *const tag, const char *const fmt, va_list va)
#include <common/macros.h>
#include <common/macros.h>
-#ifdef __MINGW_PRINTF_FORMAT
-# define BT_PRINTF_FORMAT __MINGW_PRINTF_FORMAT
-#else
-# define BT_PRINTF_FORMAT printf
-#endif
-
struct bt_param_validation_context;
struct bt_param_validation_value_descr;
struct bt_param_validation_context;
struct bt_param_validation_value_descr;
const struct bt_param_validation_map_value_entry_descr *entries,
gchar **error);
const struct bt_param_validation_map_value_entry_descr *entries,
gchar **error);
-BT_HIDDEN
-__attribute__((format(BT_PRINTF_FORMAT, 2, 3)))
+BT_HIDDEN __BT_ATTR_FORMAT_PRINTF(2, 3)
enum bt_param_validation_status bt_param_validation_error(
struct bt_param_validation_context *ctx,
const char *format, ...);
enum bt_param_validation_status bt_param_validation_error(
struct bt_param_validation_context *ctx,
const char *format, ...);