Search code examples
cc-preprocessorpragma

Macro with _Pragma - parenthesis


I'd like to simplify some preprocessor code by creating appropriate macros. I'd like to wrap

#ifdef _OPENMP
    _Pragma("omp critical(stdout)")
#endif

into a single

_OMP_CRITICAL(stdout)

so I did

#ifdef _OPENMP
    #define STRINGIFY(x) #x
    #define _OMP_CRITICAL(x)    _Pragma(STRINGIFY(omp critical(x)))
#else
    #define _OMP_CRITICAL(x)
#endif

Will it expand into what I expect? What will be passed to STRINGIFY as an "argument"? omp critical(x value), or maybe omp critical(x value? Are parenthesis matched in this situation?

A program works correctly. But I do not understand macros well, so it could possibly produce some compiling code, which will sometimes work, sometimes not. Parallel things are weird, as you probably know, so I want to make sure it is correct.


Solution

  • Yes, it has to be matched correctly. To quote C11 (n1750) §6.10.3 ¶10 (emphasis mine):

    A preprocessing directive of the form

    # define identifier lparen identifier-listopt ) replacement-list new-line
    # define identifier lparen ... ) replacement-list new-line
    # define identifier lparen identifier-list , ... ) replacement-list new-line
    

    defines a function-like macro with parameters, whose use is similar syntactically to a function call. The parameters are specified by the optional list of identifiers, whose scope extends from their declaration in the identifier list until the new-line character that terminates the #define preprocessing directive. Each subsequent instance of the function-like macro name followed by a ( as the next preprocessing token introduces the sequence of preprocessing tokens that is replaced by the replacement list in the definition (an invocation of the macro). The replaced sequence of preprocessing tokens is terminated by the matching ) preprocessing token, skipping intervening matched pairs of left and right parenthesis preprocessing tokens. Within the sequence of preprocessing tokens making up an invocation of a function-like macro, new-line is considered a normal white-space character.