Search code examples
clanguage-lawyerpragma

Are _Pragma operators allowed in the middle of function prototype declarations?


I've encountered some code like this:

void _Pragma("function") f() {
  int i = 0;
  _Pragma("loop");
  while (i < 100) {
    ...
  }
}

GCC compiles it without issues. But I don't see exactly where in the standard it allows _Pragma's to appear in such positions, especially between the void and f().

My version of the C11 standard (N1570) states:

6.10.9 Pragma operator

Semantics

A unary operator expression of the form:

_Pragma ( string-literal )

...

The example given behaves almost as #pragma, which means, on a line by its own.

Section 6.5.3. Unary operators does not even mention _Pragma.

I fail to see in the syntactic rules where unary operators would be allowed in the position between void and f().

The GCC docs just claim that:

The standard is unclear on where a _Pragma operator can appear.

I would assume that it is forbidden anywhere where not syntactically explicitly allowed.

Is it unspecifed, or implementation-defined, to allow such occurrences of _Pragma?


Solution

  • _Pragma pretty much have one single purpose: to allow you to use pragmas inside pre-processor #define macros. It isn't (shouldn't be) meaningful to use it for any other purpose.

    Other than that, 6.10.9 says:

    The resulting sequence of characters is processed through translation phase 3 to produce preprocessing tokens that are executed as if they were the pp-tokens in a pragma directive.

    You could interpret this as: meant to be written on a line of its own, since #pragma - being a pre-processor directive - works that way. In that case, since code such as void #pragma function is invalid, the same should go for _Pragma.

    To quote the gcc doc you found:

    To be safe, you are probably best keeping it out of directives other than #define, and putting it on a line of its own.

    In addition, general best practices are:

    • Don't write strange code just for the heck of it.
    • Don't use weird compiler extensions just for the heck of it.

    Although compilers should ignore unrecognized pragmas and that seems to be what gcc, clang et al are doing. Neither "compiles it without any issues" if you compile with strict settings -std=c17 -pedantic -Wall -Wextra, they warn and then ignore it.