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 #define
d, 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
_Pragma
as just a macro, and not implement it as an operator? - If not, is GCC wrong in doing so?
- if
_Pragma
is supposed to be an operator, is it undefined behavior to define_Pragma
as a macro? - Is there any ordering between
_Pragma
evaluation 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.