Иногда я пишу обертки вокруг функций в стиле printf по разным причинам, и мне действительно нравится, когда clang сообщает мне о несоответствиях типов между спецификаторами формата и фактическими аргументами.Обратите внимание:
#include <stdarg.h>
#include <stdio.h>
static __attribute__((format(printf, 1, 2))) void log(const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
vprintf(fmt, va);
va_end(va);
}
int main(void)
{
log("%s", 42);
return 0;
}
Если скомпилировано с -Wall
, это аккуратно информирует меня об ошибке этого типа:
test.c:14:15: warning: format specifies type 'char *' but the argument has type 'int' [-Wformat]
log("%s", 42);
~~ ^~
%d
Это очень хорошо работает для функций, но когда дело доходит до функции указатели , __attribute__((format(printf, 1, 2)))
, кажется, больше не действуют.Следующий код:
#include <stdarg.h>
#include <stdio.h>
typedef void (*log_t)(const char*, ...) __attribute__((format(printf, 1, 2)));
static __attribute__((format(printf, 1, 2))) void log(const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
vprintf(fmt, va);
va_end(va);
}
int main(void)
{
log_t func = &log;
(*func)("%s", 42);
return 0;
}
компилируется без предупреждений в -Wall
, но результирующая программа работает с ошибками.Я попытался поместить спецификатор атрибута в каждую часть typedef, но, похоже, это не имело значения.
Есть ли способ с помощью clang указать атрибуты (или этот атрибут)для указателей на функции, чтобы он действительно был выбран во время компиляции?
Если это имеет значение, мой кланг сообщает о своей версии как: Apple LLVM version 9.0.0 (clang-900.0.39.2)
.