In implementing my own C11 compiler, I'm trying to figure out how exactly to handle the _Pragma keyword/operator. C11 §6.10.9 describes _Pragma as being an operator, so it seems possible to redefine it with macros, i.e. #define _Pragma(x) SOME_OTHER_MACRO(x). Further, the statement #undef _Pragma should have no effect (assuming no prior #define of _Pragma). This is similar to how keywords can be #defined, such as the old VC++ hack #define for if (0) ; else for. However, because the _Pragma operator is evaluated during translation phase 3, the same phase as executing preprocessor directives, it's not clear whether this is an exception; the standard doesn't mention whether its undefined behavior to use _Pragma as a macro name.
I did some testing with GCC using the following code:
#define PRAGMA _Pragma
PRAGMA("message \"hi\"")
_Pragma ("message \"sup\"")
#undef PRAGMA
#undef _Pragma
//#define _Pragma(x)
_Pragma("message \"hello\"")
Compiling with gcc -std=c11 -pedantic -Wall -Wextra -c outputs:
tmp.c:2:1: note: #pragma message: hi
PRAGMA("message \"hi\"")
^
tmp.c:4:1: note: #pragma message: sup
_Pragma ("message \"sup\"")
^
tmp.c:8:8: warning: undefining "_Pragma" [enabled by default]
#undef _Pragma
^
tmp.c:10:9: error: expected declaration specifiers or ‘...’ before string constant
_Pragma("message \"hello\"")
^
If I add the line #undef _Alignof, GCC doesn't complain about it.
This suggests that GCC implements _Pragma through a macro (via the warning message), and that undefining it results in a compile error. If I uncomment #define _Pragma(x), the error goes away (as the string literal disappears).
So, my questions are:
- Are implementations allowed to define
_Pragmaas just a macro, and not implement it as an operator? - If not, is GCC wrong in doing so?
- if
_Pragmais supposed to be an operator, is it undefined behavior to define_Pragmaas a macro? - Is there any ordering between
_Pragmaevaluation and other preprocessor directives? Or do they have the same "precedence" (i.e. they're evaluated in-order)?
Again, looking through the C11 standard does not mention anything about _Pragma other than it's an operator that can be used for #pragma directives.