Bug 83256 - inconsistent _Pragma behavior in multi-line macros
Summary: inconsistent _Pragma behavior in multi-line macros
Alias: None
Product: gcc
Classification: Unclassified
Component: preprocessor (show other bugs)
Version: 8.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
Depends on:
Reported: 2017-12-02 14:33 UTC by Arnd Bergmann
Modified: 2019-08-29 12:53 UTC (History)
0 users

See Also:
Known to work:
Known to fail:
Last reconfirmed:

test case using _Pragma(GCC diagnostic push/pop) (288 bytes, text/plain)
2017-12-02 14:33 UTC, Arnd Bergmann
repro for similar bug, apparently broken up to 8.3 but fixed in trunk? (382 bytes, text/plain)
2018-10-09 14:17 UTC, Peter Maydell

Note You need to log in before you can comment on or make changes to this bug.
Description Arnd Bergmann 2017-12-02 14:33:17 UTC
Created attachment 42777 [details]
test case using _Pragma(GCC diagnostic push/pop)

I tried using _Pragma("GCC diagnostic push") and _Pragma("GCC diagnostic pop") inside of a multi-line macro to turn a particular warning off inside code in that macro. This worked in some cases but not others. From what I can tell, the differences are:

- If I first preprocess the file with "gcc -E", and then compile the preprocessed source, it works as expected.

- In case of the "-Wattribute-alias" warning (added in gcc-8), I get the expected behavior only if I declare a structure before the _Pragma("GCC diagnostic pop"); removing the 'struct s;' line from the attached example leads to a warning for the incompatible alias.

- With the -Wuninitialized warning, I could find no way to disabled it just inside of the macro expansion

The same thing seems to happen with multi-line statements that I join with '\' line ends even without macros, but of course there is little use in that. I did not try what happens with other. Support for _Pragma("GCC diagnostic ...") was first added in gcc-4.2. This did not yet support push/pop, but the behavior of multi-line macros was already the same as with gcc-8: preprocessing the file makes it work as expected, but the integrated preprocessor seems to evaluate the _Pragma() early.
Comment 1 Peter Maydell 2018-10-09 14:16:55 UTC
I was investigating a similar gcc bug, and was pointed at this one. I note that the test case attached to this bug seems to be (according to the godbolt compilers) broken in gcc 7.3 but fixed by 8.1.

8.1 didn't fix everything in this area, though -- I have a rather similar kind of test case (which I'll attach), which seems to be still broken in 8.3 but fixed in gcc trunk.
Comment 2 Peter Maydell 2018-10-09 14:17:59 UTC
Created attachment 44817 [details]
repro for similar bug, apparently broken up to 8.3 but fixed in trunk?
Comment 3 joseph@codesourcery.com 2018-10-09 15:22:34 UTC
Unless someone can identify a commit that deliberately fixed the bug *and 
added appropriate tests to the testsuite*, I'd strongly advise adding 
tests to the testsuite before marking FIXED on the basis of those tests 
now passing (if they are passing incidentally as a result of some other 
change that didn't add tests directly related to this bug).
Comment 4 Mark Rohrbacher 2019-08-29 12:53:52 UTC
I tried to achieve something very similar to temporarily enable -Wswitch-enum just for a single switch:

#define SWITCH_ENUM(x) \
    _Pragma("GCC diagnostic push") \
    _Pragma("GCC diagnostic warning \"-Wswitch-enum\"") \
    switch(x) \
    _Pragma("GCC diagnostic pop")

which doesn't work as expected in gcc7.4 and gcc8.4 (it works however in 9.1, 9.2 and trunk). Manually expanding the macro (as well as compiling the preprocessor output) leads to the expected result.

It seems that the evaluation of _Pragma in macros happens after the 'real' source code of the macro, so
#define _Pragma("X") my_code_here
seems to be interpreted as
#define my_code_here _Pragma("X")

When omitting _Pragma("GCC diagnostic pop") in the macro, -Wswitch-enum is enabled within the switch body, but disabled for the switch itself.