0

It's often undesirable but sometimes unavoidable to emit #pragma directives to suppress and restore warnings. Some compilers support _Pragma as a way to, among other things, control diagnostics from inside a macro expression.

How to concatenate strings in the arguments of _Pragma discusses how to paste a single string into a _Pragma statement.

Is there any way to parameterize this? I'd like to combine both _Pragma directives behind one macro, but that requires pasting tokens together inside of a _Pragma statement:

#define DO_A_THING(SOME_FLOAT) \
  do { \
    DISABLE_COMPILER_WARNING(double-promotion) \
    call_variadic_function("blah", SOME_FLOAT) \
    RESTORE_COMPILER_WARNING() \
  } while(0)

DISABLE_COMPILER_WARNING would expand into something like:

    _Pragma("GCC diagnostic push") \
    _Pragma("GCC diagnostic ignored \"-Wdouble-promotion\"")

and RESTORE_COMPILER_WARNING would expand into something like:

    _Pragma("GCC diagnostic pop")

Is there a way to author DISABLE_COMPILER_WARNING to expand out as written?

Charles Nicholson
  • 888
  • 1
  • 8
  • 21

1 Answers1

2

Works:

// double expand for proper "something \"something\""
#define PRAGMA_DO1(X) _Pragma(#X)
#define PRAGMA_DO(X) PRAGMA_DO1(GCC diagnostic ignored #X)

#define DISABLE_COMPILER_WARNING(X) \
    _Pragma("GCC diagnostic push") \
    PRAGMA_DO(-W##X)

#define RESTORE_COMPILER_WARNING()  \
    _Pragma("GCC diagnostic pop")
    
#define DO_A_THING(SOME_FLOAT) \
  do { \
    DISABLE_COMPILER_WARNING(double-promotion) \
    call_variadic_function("blah", SOME_FLOAT); \
    RESTORE_COMPILER_WARNING() \
  } while(0)

void call_variadic_function(const char *str, ...);

int main() {
    // call_variadic_function("blah", (float)1);
    DO_A_THING((float)1);
}
KamilCuk
  • 120,984
  • 8
  • 59
  • 111