Created attachment 43809 [details] The preprocessed source, which works as expected The preprocessed output (attached) behaves as expected, so I assume this problem has to do with the driver and/or a strange interaction between driver, preprocessor and compiler. For lack of better knowledge, I've filed this bug under the "driver" component. The whole code is on godbolt: https://godbolt.org/g/rTc3AU Given the following code, g++ properly emits a warning. int x; int test1(int val) { switch (val) { if (!x) { case 1: return 10; } } return 0; } pragmatest.cpp: In function ‘int test1(int)’: pragmatest.cpp:5:25: warning: statement will never be executed [-Wswitch-unreachable] if (!x) { ^~ If I then try to silence this warning with the proper _Pragma directive, in clear, like in the following code, it works as expected as in the compiler doesn't complain any longer: int test2(int val) { switch (val) { _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wswitch-unreachable\"") if (!x) { _Pragma("GCC diagnostic pop") case 1: return 10; } } return 0; } If I then try to to hide the pragmas within 2 macros, like in the following code, it still works: #define B _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wswitch-unreachable\"") #define E _Pragma("GCC diagnostic pop") int test3(int val) { switch (val) { B if (!x) E { case 1: return 10; } } return 0; } However, if now I want to turn the whole "B if (!x) E" statement into a define of its own, like in the following code, it doesn't work any longer. #define X() B if (!x) E int test4(int val) { switch (val) { X() { case 1: return 10; } } return 0; } pragmatest.cpp: In function ‘int test4(int)’: pragmatest.cpp:39:23: warning: statement will never be executed [-Wswitch-unreachable] #define X() B if (!x) E ^~ pragmatest.cpp:43:21: note: in expansion of macro ‘X’ X() { ^ This looked quite odd, and at first thought I couldn't figure out what was going on, but then I thought of using a layer of indirection around the pragma macros, thinking it might have something to do with secondary expansion, so I tried the following code, but still no luck. #define Y(x) x #define X2() Y(B) if (!x) Y(E) int test5(int val) { switch (val) { X2() { case 1: return 10; } } return 0; } pragmatest.cpp: In function ‘int test5(int)’: pragmatest.cpp:52:27: warning: statement will never be executed [-Wswitch-unreachable] #define X2() Y(B) if (!x) Y(E) ^~ pragmatest.cpp:55:21: note: in expansion of macro ‘X2’ X2() { ^~ So I tried something which in my mind wouldn't make sense at all - notice that I wrapped the x **variable** in the Y() macro - but what did I have to lose anyway? But the following code still (unsurprinsigly?) didn't work: #define X3() Y(B) if (!Y(x)) Y(E) int test6(int val) { switch (val) { X3() { case 1: return 10; } } return 0; } pragmatest.cpp: In function ‘int test6(int)’: pragmatest.cpp:63:27: warning: statement will never be executed [-Wswitch-unreachable] #define X3() Y(B) if (!Y(x)) Y(E) ^ pragmatest.cpp:66:21: note: in expansion of macro ‘X3’ X3() { ^~ However this time around the warning message gave me a hint! Why would the compiler complain only about the exclamation mark not being reachable? So I tried the following... and it worked! #define X4() Y(B) if (Y(!)x) Y(E) int test7(int val) { switch (val) { X4() { case 1: return 10; } } return 0; } That code above makes the compiler stay silent, against all odds. So I thought: let's see if removing the Y() wrapping around the pragma macros still works. Nope, it didn't. #define X5() B if (Y(!)x) E int test8(int val) { switch (val) { X5() { case 1: return 10; } } return 0; } pragmatest.cpp: In function ‘int test8(int)’: pragmatest.cpp:85:26: warning: statement will never be executed [-Wswitch-unreachable] #define X5() B if (Y(!)x) E ^ pragmatest.cpp:51:18: note: in definition of macro ‘Y’ #define Y(x) x ^ pragmatest.cpp:88:21: note: in expansion of macro ‘X5’ X5() { ^~ Again, the compiler indicated that the error has to do with the exclamation mark.
Created attachment 43810 [details] The preprocessed source, which works as expected The real one. The previous one was from another test.
And removing the exclamation mark from the if condition actually makes it work again, but only if the B and E macro are wrapped within the Y() macro, otherwise it still complains, now indicating the parenthesis as the problem: #define X6() B if (x) E int test9(int val) { switch (val) { X6() { case 1: return 10; } } return 0; } pragmatest.cpp: In function ‘int test9(int)’: pragmatest.cpp:96:25: warning: statement will never be executed [-Wswitch-unreachable] #define X6() B if (x) E ^ pragmatest.cpp:99:21: note: in expansion of macro ‘X6’ X6() { ^~
Confirmed. Not sure what the exact limit is but some of the warnings can only be disabled at function granularity and placing the pragmas in macros might interfere with this.
@(In reply to Richard Biener from comment #3) > Confirmed. Not sure what the exact limit is but some of the warnings can > only be disabled at function granularity and placing the pragmas in macros > might interfere with this. But the preprocessed output shows the #pragma's all at the expected place and compiling the preprocessed output works as expected. I only ever delved into gcc's innards in one of its old releases and don't know if anything has changed meanwhile about this, but afaik the compiler always works on the preprocessed output, and if this still holds true, how can it be explained that invoking g++ on the un-preprocessed output produces a different result than invoking it on the preprocessed output?
I was looking to see if this bug had been fixed in gcc trunk, and if you tell godbolt to run the non-preprocessed original code on gcc trunk (ie the source you get by following the godbolt link in comment 1), the compiler ICEs: <source>: In function 'int test7(int)': <source>:76:5: internal compiler error: in linemap_macro_map_loc_to_exp_point, at libcpp/line-map.c:1063 76 | switch (val) { | ^~~~~~ Please submit a full bug report, with preprocessed source if appropriate. See <https://gcc.gnu.org/bugs/> for instructions. Compiler returned: 1 (There are a whole set of these "_Pragma() to disable diagnostics doesn't do the right thing" bugs in bugzilla. So far I have seen test cases which have been fixed in gcc 8, test cases fixed in trunk but not 8, and this one which is differently-broken in trunk. So there isn't a single underlying bug in all cases.)
This was the same issue as PR91669. Fixed by r10-325 and a testcase was added in r13-3051. *** This bug has been marked as a duplicate of bug 91669 ***