Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

_Pragma and macro substitution

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:

  1. Are implementations allowed to define _Pragma as just a macro, and not implement it as an operator?
  2. If not, is GCC wrong in doing so?
  3. if _Pragma is supposed to be an operator, is it undefined behavior to define _Pragma as a macro?
  4. 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.

like image 418
Drew McGowen Avatar asked Jul 23 '14 16:07

Drew McGowen


Video Answer


1 Answers

There is no need for a special rule that would forbid _Pragma to be a macro name. Having a leading underscore and capital letter, it is among the reserved identifiers that you are not supposed to use, anyhow. Using reserved identifiers leads to undefined behavior of your program, a compiler may do anything.

An implementation may implement it as a macro, but that should be transparent to you, as long as you use it correctly, that is as long as you don't mess around with it. The only important thing that an implementation must guarantee is that the "destringization" and "tokeninzation" of the argument to the _Pragma is done as if in phase 3 (which is difficult if it is "only" a macro) and that the resulting #pragma directive is processed in phase 4.

like image 71
Jens Gustedt Avatar answered Oct 21 '22 06:10

Jens Gustedt