Multiple _Pragmas cause errors

Started by nemequ, April 12, 2019, 08:09:00 PM

Previous topic - Next topic

nemequ

I recently added support for Pelles C to one of my projects (Hedley), and I noticed that "calling" _Pragma multiple times on a single line causes errors.  This is particularly annoying in preprocessor macros, so here's a quick test for that:

#define FOO_DLLEXPORT \
  _Pragma("warn(push)") \
  _Pragma("warn(disable:2016)") \
  __declspec(dllexport) \
  _Pragma("warn(pop)")

FOO_DLLEXPORT
void foo(void) { }


Results in

pragmas.c(7): error #1017: Syntax error in directive.
pragmas.c(7): warning #2099: Missing type specifier; assuming 'int'.
pragmas.c(7): error #2001: Syntax error: expected ')' but found 'string constant'.
pragmas.c(7): error #2001: Syntax error: expected ';' but found '_Pragma'.
pragmas.c(7): warning #2099: Missing type specifier; assuming 'int'.
pragmas.c(7): error #2001: Syntax error: expected ')' but found 'string constant'.
pragmas.c(7): warning #2117: Old-style function definition for '_Pragma'.
pragmas.c(7): warning #2016: Use of __declspec(dllexport) requires the /Ze option; ignored.
pragmas.c(7): warning #2099: Missing type specifier; assuming 'int'.
pragmas.c(7): error #2001: Syntax error: expected ')' but found 'string constant'.
pragmas.c(8): error #2001: Syntax error: expected ';' but found 'void'.
pragmas.c(8): error #2001: Syntax error: expected ';' but found '{'.
pragmas.c(8): error #2011: Declared parameter 'foo' is missing.
pragmas.c(7): error #2011: Declared parameter '_Pragma' is missing.
error #2001: Syntax error: expected '{' but found 'end of input'.
error #2001: Syntax error: expected '}' but found 'end of input'.


On the other hand, this works:

#pragma warn(push)
#pragma warn(disable:2016)
__declspec(dllexport)
#pragma warn(pop)
void foo(void) { }


As does

_Pragma("warn(push)")
_Pragma("warn(disable:2016)")
__declspec(dllexport)
_Pragma("warn(pop)")
void foo(void) { }

frankie

Have you considered that the expansion will give:

_Pragma("warn(push)") _Pragma("warn(disable:2016)") __declspec(dllexport) _Pragma("warn(pop)")


not (as probably you wished):

_Pragma("warn(push)")
_Pragma("warn(disable:2016)")
__declspec(dllexport)
_Pragma("warn(pop)")


The first is wrong, and for this reason the compiler complains.
For the same reason this shouldn't be a bug.
"It is better to be hated for what you are than to be loved for what you are not." - Andre Gide

nemequ

Yes, that's why I mentioned that the problem was with using _Pragma "multiple times on a single line", and provided an example where the _Pragmas were on multiple lines and worked.  Sorry, I could have made it a bit more explicit, but yeah I agree that the problem occurs when you use multiple _Pragma operators on a single line.

I'm not sure why you think multiple pragma operators on a single line would be wrong, though.  The C11 specification defines the pragma operator in § 6.10.9:

QuoteA unary operator expression of the form:_Pragma ( string-literal )is processed as follows: The string literal is destringized by deleting any encoding prefix, deleting the leading and trailing double-quotes, replacing each escape sequence \" by a double-quote, and replacing each escape sequence \\ by a single backslash. 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. The original four preprocessing tokens in the unary operator expression are removed.

That seems pretty clear to me; the pragmas should be treated separately "as if they were the pp-tokens in a pragma directive", not mapped to an actual pragma directive without a new-line to terminate it.

It does mention that the pragma directive can also be expressed with a pragma operator, but I don't see anything to indicate that the operator should be converted by the compiler to an actual directive, much less one without a terminating new-line.  It's also interesting that the direction of the example is from directive to operator, not operator to directive.

frankie

I see.
For some reason the compiler stops evaluating _Pragma operator after the first one and try to parse the line remaining as code.
Seems to be a bug.
"It is better to be hated for what you are than to be loved for what you are not." - Andre Gide

Pelle

I will think about it. I don't find the C standard text about _Pragma to be very clear and helpful.
Some other compilers seem to support this, so I might add it, but we'll see...
/Pelle