Im interested to add in some extra logic around existing function calls, by wrapping them without renaming them. (just for a test).
The existin
For example, lets say I want to check the types on a function call.
A simple case, I want to check that sqrt
only takes (int
or double
), not float
.
Here is a method that works OK.
/* add this to a header or at the top of the source-code */
#include <math.h>
static typeof(&sqrt) sqrt_wrap = sqrt;
#define sqrt(f) (_Generic((f), int: sqrt_wrap, double: sqrt_wrap))(f)
This works but has some drawbacks.
<math.h>
, or at least define sqrt
since we dont know if the static function is called or not.__attribute__((__unused__))
works in works in GCC/Clang.sqrt
.Edit!
This does in fact work, the header just needs to be included first (obviously - in retrospect)
#include <math.h>
#define sqrt(f) _Generic((f), int: sqrt(f), double: sqrt(f))
Heres a trick to check sqrt
isn't called with float
and sqrtf
isn't called with double
#include <math.h>
#define sqrt(X) _Generic((X), float: NULL, default: sqrt)(X)
#define sqrtf(X) _Generic((X), double: NULL, default: sqrtf)(X)
There's normally no need to rename macro-wrapped functions because inside the expansion of a macro, the macro's name is not expanded.
Here's an example straight from the C11 standard:
#define cbrt(X) _Generic((X), \
long double: cbrtl, \
default: cbrt, \
float: cbrtf \
)(X)
Of course, you'll run into problems if you've #include <tgmath.h>
because in that case you'll already have type-generic macros, such as the above, and you won't be able to redefine sqrt
(unless you #undef
it). And you must #include <math.h>
before defining that macro.
Even so, you're treading on thin ice. The standard reserves the names of standard library functions, and insists that (§7.1.3/2):
If the program declares or defines an identifier in a context in which it is reserved (other than as allowed by 7.1.4), or defines a reserved identifier as a macro name, the behavior is undefined.
The referenced section 7.1.4 does allow you to #undef
a function-like macro which shadows a standard-library function, but it is not clear to me that you are allowed to subsequently redefine it. YMMV.
If you wanted to use _Generic
to call a wrapper function, you can still make that work without renaming the original function. For example:
#include <nanny.h>
/* In this file, you can't call nanny(char), and if you call it
* with an unsigned argument, we'll insert an additional check
*/
#define nanny(X) _Generic((X), int: nanny, unsigned:nanny_wrapper)(X)
int nanny_wrapper(unsigned x) {
assert(x < INT_MAX);
/* The redundant parentheses prevent macro expansion */
return (nanny)(x);
}