Search code examples
cgccmacrosmasking

Define a function which function name is masked by a macro


Sometimes, it can be handy to mask a function by a macro of same name. In this contrived example, the macros makes it possible to insert additional verification while calling function().

int function(int i);

#define function(i)  ( assert(i>0), function(i) )

Other more common usages make the macro translate into faster code, like a direct table entry point, for improved performance. In all cases, the goal is to preserve the symbol of same name in the library, to ensure it exists and can be invoked from the library by another program without requiring the *.h (typically from a wrapper in a language different from C).

In the corresponding unit, defining function() now has a problem : function is now a macros. So int function(int i) { ... } will be expanded, and fail pretty badly.

The solution to this problem is simple : just #undef function before the definition, and then implement the function.

All is fine, except that ...

If, in a later section of the same unit, another function invokes function(), it will now invoke the symbol directly, instead of the macro in the *.h, thus losing the extra-functionalities provided by the macros, which might be undesirable.

Another work-around to this issue is available in gcc, using compiler extension #pragma push_macro. It works, but is pretty much ugly, adding a minimum of 3 lines around the function definition, which doesn't help for readability. And this is without counting portability shenanigans, which will add more complexity.

Yet, masking a function with a macro of same name isn't new. I'm pretty sure I've read books suggesting this design as far back as C90 standard libraries.

I'm suspecting a better solution to this problem might exist. Any idea ?


Solution

  • An alternative trick for function-like macros is to put redundant parentheses around the declarator in the definition:

    int (function)(int i) {
        ...
    }
    

    This prevents the function-like macro from matching and expanding, but has no effect on the definition.