Search code examples
c++macroscompiler-warningssuppress-warnings

silence warnings about unused variables/functions at the point of their conditionally compiled usage


So in doctest (my testing framework) the user can disable all tests by defining the DOCTEST_CONFIG_DISABLE identifier which makes the following code and macros:

TEST_CASE("name") {
    int a = 5;
    int b = 6;
    CHECK(a == b);
}

turn into the following after the preprocessor:

template<typename T>
void some_anon_func_123() {
    int a = 5;
    int b = 6;
}

that means that the self-registering test case is turned into an uninstantiated template function and the CHECK() macro (which functions as an if statement checking the condition) into a no-op - like this:

#define CHECK(x) ((void)0) // if disabled

However if the user has factored such testing code in a separate function like this:

static int g() {
    std::cout << "called!" << std::endl;
    return 42;
}

static void f() {
    int a = 5;
    CHECK(a == g());
}

TEST_CASE("name") {
    f();
}

then there will be warnings for unused functions and unused variables. doctest prides itself with producing 0 warnings even on the most aggressive levels so this is unacceptable.

I tried using the ((void) ...) trick by passing it the macro argument like this:

#define CHECK(x) ((void)(x))

and that indeed silenced the warnings (atleast for a and g()) but there is still code being generated for that statement - if I invoke the f() function from my main() I will see the called! string printed in the console. This is undesirable since I want the compilation to be as fast as possible when test cases and asserts are disabled from the build (by using the DOCTEST_CONFIG_DISABLE identifier). If a user has 100 000 asserts and builds with them disabled he wouldn't want all that unnecessary codegen and compile time overhead for macros that are supposed to be disabled (the CHECK() one).

__attribute__((unused)) has to be used at the point of declaration of a variable - I cannot stick it in the CHECK() macro (or can I? I don't know...).

Not sure if _Pragma() could help - and even if it could - it is known to have issues with GCC:

Is there a solution to my problem - like perhaps passing the expression to some template or whatever...? (C++98 solution needed)

I explained my problem in excruciating detail only because I often get accused of the XY problem...

EDIT:

A C++11 solution is OK too - some C++11 features have started to conditionally creep into the library anyway...


Solution

  • So, you want to "lie" to the compiler that you're using a function which you're not actually calling. So how to use a piece of code without executing it?

    It seems that the only thing that works on all popular compilers is a C++11-only solution - a lambda which is never called:

    #define CHECK(x) [&](){ ((void)(x)); }
    

    If you absolutely need a c++98 solution, a sizeof will also work on many compilers, MSVC being a notable exception:

    #define CHECK(x) sizeof(x)
    

    MSVC will still warn for uncalled functions in the expression x.

    I guess for maximum coverage you could employ a combination of the two.