Suppose I am maintaining a library function that takes two arguments, both pointers. The second argument exists only for backward compatibility; callers should always pass a NULL. I would like to put something into my header file that makes the compiler issue warnings if the second argument is not a compile-time constant NULL. I thought I would be able to do this using GCC's __builtin_constant_p and __attribute__((warning)) extensions:
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);
}
But this doesn't work with any version of GCC I have tested. I get warnings for both calls to thefun. (Compiler Explorer demo.)
Can anyone suggest an alternative construct that will produce a warning for warning_expected, and not for warning_not_expected ?
Notes:
- Curiously, the above does work if
bis anint. - The above uses GCC-specific extensions, however a solution that works on a broader variety of compilers would be welcome. (In particular, clang does not implement
attribute((warning))and I haven't had any luck finding an alternative.) - A solution that still works when optimization is turned off would be preferable to one that doesn't. (The above does not work with optimization turned off, even if
bis anintandthefunis marked always-inline.) - A solution that doesn't involve defining
thefunas a macro would be preferable to one that does. - The header has to work when included from C programs and from C++ programs. A modest amount of ifdeffage is acceptable.
- It must be a warning, not a hard error, unless
-Werroror equivalent is active.
EDIT: Based on Kamil Cuk's discovery that the unwanted warning can be suppressed by casting the pointer to an integer of a different size, I have determined that this is an oversight in the implementation of __builtin_constant_p and filed GCC bug report #91554. I'd still be interested in answers that provide ways to do this with clang, icc, or any other compiler that's commonly used together with GNU libc.