Предположим, я поддерживаю библиотечную функцию, которая принимает два аргумента, оба указателя. Второй аргумент существует только для обратной совместимости; абоненты должны всегда передавать NULL. Я хотел бы поместить что-то в мой заголовочный файл, который заставляет компилятор выдавать предупреждения, если второй аргумент не является константой времени компиляции NULL. Я думал, что смогу сделать это, используя расширения GCC __builtin_constant_p
и __attribute__((warning))
:
extern void thefun_called_with_nonnull_arg (void)
__attribute__((__warning__(
"'thefun' called with second argument not NULL")));
extern int real_thefun (void *, void *);
static inline int
thefun (void *a, void *b)
{
if (!__builtin_constant_p(b) || b != 0)
thefun_called_with_nonnull_arg();
return real_thefun(a, b);
}
int warning_expected (void *a, void *b)
{
return thefun(a, b);
}
int warning_not_expected (void *a)
{
return thefun(a, 0);
}
Но это не работает с любой версией GCC, которую я тестировал. Я получаю предупреждения для обоих звонков на thefun
. (Демонстрация компилятора.)
Кто-нибудь может предложить альтернативную конструкцию, которая выдаст предупреждение для warning_expected
, а не для warning_not_expected
?
Примечания:
- Любопытно, что вышеприведенное действительно работает, если
b
являетсяint
. - Выше используются специфичные для GCC расширения, однако приветствуется решение, которое работает на более широком спектре компиляторов. (В частности, Clang не реализует
attribute((warning))
, и мне не повезло найти альтернативу.) - Решение, которое все еще работает, когда оптимизация выключена, было бы предпочтительнее решения, которое не работает. (Вышеприведенное не работает с отключенной оптимизацией, даже если
b
являетсяint
иthefun
помечен всегда встроенным.) - Решение, которое не включает определение
thefun
в качестве макроса, было бы предпочтительнее того, которое делает. - Заголовок должен работать при включении из программ на C и программ C++. Скромное количество ifdeffage является приемлемым.
- Это должно быть предупреждение, а не серьезная ошибка, если только
-Werror
или его эквивалент не активен.
ОБНОВЛЕНИЕ: На основании открытия Камила Цука о том, что нежелательное предупреждение можно подавить, приведя указатель к целому числу другого размера, я определил, что это упущение при реализации __builtin_constant_p
и подал отчет об ошибке GCС# 91554. Мне все еще будут интересны ответы, которые предоставляют способы сделать это с помощью clang, icc или любого другого компилятора, который обычно используется вместе с GNU libc.